restore multi_buffer.rs

Cole Miller created

Change summary

crates/multi_buffer/src/multi_buffer.rs | 524 +++++---------------------
1 file changed, 114 insertions(+), 410 deletions(-)

Detailed changes

crates/multi_buffer/src/multi_buffer.rs 🔗

@@ -36,9 +36,7 @@ use std::{
     any::type_name,
     borrow::Cow,
     cell::{Cell, Ref, RefCell},
-    cmp,
-    collections::VecDeque,
-    fmt::{self, Debug},
+    cmp, fmt,
     future::Future,
     io,
     iter::{self, FromIterator},
@@ -63,9 +61,6 @@ pub use self::path_key::PathKey;
 #[derive(Debug, Default, Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)]
 pub struct ExcerptId(u32);
 
-#[derive(Debug, Default, Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)]
-pub struct BaseTextRow(pub u32);
-
 /// One or more [`Buffers`](Buffer) being edited in a single view.
 ///
 /// See <https://zed.dev/features#multi-buffers>
@@ -92,14 +87,6 @@ pub struct MultiBuffer {
     /// The writing capability of the multi-buffer.
     capability: Capability,
     buffer_changed_since_sync: Rc<Cell<bool>>,
-    follower: Option<Entity<MultiBuffer>>,
-    filter_mode: Option<MultiBufferFilterMode>,
-}
-
-#[derive(Clone, Copy, Debug, PartialEq, Eq)]
-pub enum MultiBufferFilterMode {
-    KeepInsertions,
-    KeepDeletions,
 }
 
 #[derive(Clone, Debug, PartialEq, Eq)]
@@ -152,8 +139,6 @@ pub struct MultiBufferDiffHunk {
     pub diff_base_byte_range: Range<BufferOffset>,
     /// Whether or not this hunk also appears in the 'secondary diff'.
     pub secondary_status: DiffHunkSecondaryStatus,
-    /// The word diffs for this hunk.
-    pub word_diffs: Vec<Range<MultiBufferOffset>>,
 }
 
 impl MultiBufferDiffHunk {
@@ -563,33 +548,25 @@ pub struct MultiBufferSnapshot {
 }
 
 #[derive(Debug, Clone)]
-/// A piece of text in the multi-buffer
 enum DiffTransform {
-    Unmodified {
+    BufferContent {
         summary: MBTextSummary,
-    },
-    InsertedHunk {
-        summary: MBTextSummary,
-        hunk_info: DiffTransformHunkInfo,
-    },
-    FilteredInsertedHunk {
-        summary: MBTextSummary,
-        hunk_info: DiffTransformHunkInfo,
+        inserted_hunk_info: Option<DiffTransformHunkInfo>,
     },
     DeletedHunk {
         summary: TextSummary,
         buffer_id: BufferId,
         hunk_info: DiffTransformHunkInfo,
+        base_text_byte_range: Range<usize>,
         has_trailing_newline: bool,
     },
 }
 
-#[derive(Clone, Debug)]
+#[derive(Clone, Copy, Debug)]
 struct DiffTransformHunkInfo {
     excerpt_id: ExcerptId,
     hunk_start_anchor: text::Anchor,
     hunk_secondary_status: DiffHunkSecondaryStatus,
-    base_text_byte_range: Range<usize>,
 }
 
 impl Eq for DiffTransformHunkInfo {}
@@ -616,15 +593,6 @@ pub struct ExcerptInfo {
     pub end_row: MultiBufferRow,
 }
 
-/// Used with [`MultiBuffer::push_buffer_content_transform`]
-#[derive(Clone, Debug)]
-struct CurrentInsertedHunk {
-    hunk_excerpt_start: ExcerptOffset,
-    insertion_end_offset: ExcerptOffset,
-    hunk_info: DiffTransformHunkInfo,
-    is_filtered: bool,
-}
-
 impl std::fmt::Debug for ExcerptInfo {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         f.debug_struct(type_name::<Self>())
@@ -664,7 +632,6 @@ pub struct ExpandInfo {
 pub struct RowInfo {
     pub buffer_id: Option<BufferId>,
     pub buffer_row: Option<u32>,
-    pub base_text_row: Option<BaseTextRow>,
     pub multibuffer_row: Option<MultiBufferRow>,
     pub diff_status: Option<buffer_diff::DiffHunkStatus>,
     pub expand_info: Option<ExpandInfo>,
@@ -960,12 +927,10 @@ impl<'a, MBD: MultiBufferDimension> Dimension<'a, DiffTransformSummary> for Diff
 struct MultiBufferCursor<'a, MBD, BD> {
     excerpts: Cursor<'a, 'static, Excerpt, ExcerptDimension<MBD>>,
     diff_transforms: Cursor<'a, 'static, DiffTransform, DiffTransforms<MBD>>,
-    snapshot: &'a MultiBufferSnapshot,
+    diffs: &'a TreeMap<BufferId, BufferDiffSnapshot>,
     cached_region: Option<MultiBufferRegion<'a, MBD, BD>>,
 }
 
-/// Matches transformations to an item
-/// This is essentially a more detailed version of DiffTransform
 #[derive(Clone)]
 struct MultiBufferRegion<'a, MBD, BD> {
     buffer: &'a BufferSnapshot,
@@ -973,21 +938,10 @@ struct MultiBufferRegion<'a, MBD, BD> {
     diff_hunk_status: Option<DiffHunkStatus>,
     excerpt: &'a Excerpt,
     buffer_range: Range<BD>,
-    diff_base_byte_range: Option<Range<usize>>,
     range: Range<MBD>,
     has_trailing_newline: bool,
 }
 
-impl<'a, MBD, BD> MultiBufferRegion<'a, MBD, BD>
-where
-    MBD: Ord,
-    BD: Ord,
-{
-    fn is_filtered(&self) -> bool {
-        self.range.is_empty() && self.buffer_range.is_empty() && self.diff_hunk_status == None
-    }
-}
-
 struct ExcerptChunks<'a> {
     excerpt_id: ExcerptId,
     content_chunks: BufferChunks<'a>,
@@ -1100,8 +1054,6 @@ impl MultiBuffer {
             paths_by_excerpt: Default::default(),
             buffer_changed_since_sync: Default::default(),
             history: History::default(),
-            follower: None,
-            filter_mode: None,
         }
     }
 
@@ -1135,8 +1087,8 @@ impl MultiBuffer {
         Self {
             snapshot: RefCell::new(self.snapshot.borrow().clone()),
             buffers: buffers,
-            excerpts_by_path: self.excerpts_by_path.clone(),
-            paths_by_excerpt: self.paths_by_excerpt.clone(),
+            excerpts_by_path: Default::default(),
+            paths_by_excerpt: Default::default(),
             diffs: diff_bases,
             subscriptions: Default::default(),
             singleton: self.singleton,
@@ -1144,46 +1096,6 @@ impl MultiBuffer {
             history: self.history.clone(),
             title: self.title.clone(),
             buffer_changed_since_sync,
-            follower: None,
-            filter_mode: None,
-        }
-    }
-
-    pub fn get_or_create_follower(&mut self, cx: &mut Context<Self>) -> Entity<MultiBuffer> {
-        use gpui::AppContext as _;
-
-        if let Some(follower) = &self.follower {
-            return follower.clone();
-        }
-
-        let follower = cx.new(|cx| self.clone(cx));
-        follower.update(cx, |follower, _cx| {
-            follower.capability = Capability::ReadOnly;
-        });
-        self.follower = Some(follower.clone());
-        follower
-    }
-
-    pub fn set_filter_mode(&mut self, new_mode: Option<MultiBufferFilterMode>) {
-        self.filter_mode = new_mode;
-        let excerpt_len = self
-            .snapshot
-            .get_mut()
-            .diff_transforms
-            .summary()
-            .excerpt_len();
-        let edits = Self::sync_diff_transforms(
-            self.snapshot.get_mut(),
-            vec![Edit {
-                old: ExcerptDimension(MultiBufferOffset(0))..excerpt_len,
-                new: ExcerptDimension(MultiBufferOffset(0))..excerpt_len,
-            }],
-            // TODO(split-diff) is this right?
-            DiffChangeKind::BufferEdited,
-            new_mode,
-        );
-        if !edits.is_empty() {
-            self.subscriptions.publish(edits);
         }
     }
 
@@ -1666,7 +1578,7 @@ impl MultiBuffer {
         cx: &mut Context<Self>,
     ) -> Vec<ExcerptId>
     where
-        O: text::ToOffset + Clone,
+        O: text::ToOffset,
     {
         self.insert_excerpts_after(ExcerptId::max(), buffer, ranges, cx)
     }
@@ -1704,7 +1616,7 @@ impl MultiBuffer {
         cx: &mut Context<Self>,
     ) -> Vec<ExcerptId>
     where
-        O: text::ToOffset + Clone,
+        O: text::ToOffset,
     {
         let mut ids = Vec::new();
         let mut next_excerpt_id =
@@ -1733,13 +1645,10 @@ impl MultiBuffer {
         ranges: impl IntoIterator<Item = (ExcerptId, ExcerptRange<O>)>,
         cx: &mut Context<Self>,
     ) where
-        O: text::ToOffset + Clone,
+        O: text::ToOffset,
     {
-        // TODO(split-diff) see if it's worth time avoiding collecting here later
-        let collected_ranges: Vec<_> = ranges.into_iter().collect();
-
         assert_eq!(self.history.transaction_depth(), 0);
-        let mut ranges = collected_ranges.iter().cloned().peekable();
+        let mut ranges = ranges.into_iter().peekable();
         if ranges.peek().is_none() {
             return Default::default();
         }
@@ -1839,23 +1748,11 @@ impl MultiBuffer {
                 new: edit_start..edit_end,
             }],
             DiffChangeKind::BufferEdited,
-            self.filter_mode,
         );
         if !edits.is_empty() {
             self.subscriptions.publish(edits);
         }
 
-        if let Some(follower) = &self.follower {
-            follower.update(cx, |follower, cx| {
-                follower.insert_excerpts_with_ids_after(
-                    prev_excerpt_id,
-                    buffer.clone(),
-                    collected_ranges,
-                    cx,
-                );
-            })
-        }
-
         cx.emit(Event::Edited {
             edited_buffer: None,
         });
@@ -1905,16 +1802,10 @@ impl MultiBuffer {
                 new: start..start,
             }],
             DiffChangeKind::BufferEdited,
-            self.filter_mode,
         );
         if !edits.is_empty() {
             self.subscriptions.publish(edits);
         }
-        if let Some(follower) = &self.follower {
-            follower.update(cx, |follower, cx| {
-                follower.clear(cx);
-            })
-        }
         cx.emit(Event::Edited {
             edited_buffer: None,
         });
@@ -2203,22 +2094,10 @@ impl MultiBuffer {
             snapshot.trailing_excerpt_update_count += 1;
         }
 
-        let edits = Self::sync_diff_transforms(
-            &mut snapshot,
-            edits,
-            DiffChangeKind::BufferEdited,
-            self.filter_mode,
-        );
+        let edits = Self::sync_diff_transforms(&mut snapshot, edits, DiffChangeKind::BufferEdited);
         if !edits.is_empty() {
             self.subscriptions.publish(edits);
         }
-
-        if let Some(follower) = &self.follower {
-            follower.update(cx, |follower, cx| {
-                follower.remove_excerpts(ids.clone(), cx);
-            })
-        }
-
         cx.emit(Event::Edited {
             edited_buffer: None,
         });
@@ -2374,7 +2253,6 @@ impl MultiBuffer {
             DiffChangeKind::DiffUpdated {
                 base_changed: base_text_changed,
             },
-            self.filter_mode,
         );
         if !edits.is_empty() {
             self.subscriptions.publish(edits);
@@ -2537,14 +2415,7 @@ impl MultiBuffer {
             text::Anchor::min_max_range_for_buffer(buffer_id),
             cx,
         );
-        self.diffs
-            .insert(buffer_id, DiffState::new(diff.clone(), cx));
-
-        if let Some(follower) = &self.follower {
-            follower.update(cx, |follower, cx| {
-                follower.add_diff(diff, cx);
-            })
-        }
+        self.diffs.insert(buffer_id, DiffState::new(diff, cx));
     }
 
     pub fn diff_for(&self, buffer_id: BufferId) -> Option<Entity<BufferDiff>> {
@@ -2657,7 +2528,6 @@ impl MultiBuffer {
             &mut snapshot,
             excerpt_edits,
             DiffChangeKind::ExpandOrCollapseHunks { expand },
-            self.filter_mode,
         );
         if !edits.is_empty() {
             self.subscriptions.publish(edits);
@@ -2745,16 +2615,7 @@ impl MultiBuffer {
         drop(cursor);
         snapshot.excerpts = new_excerpts;
 
-        if let Some(follower) = &self.follower {
-            follower.update(cx, |follower, cx| follower.resize_excerpt(id, range, cx));
-        }
-
-        let edits = Self::sync_diff_transforms(
-            &mut snapshot,
-            edits,
-            DiffChangeKind::BufferEdited,
-            self.filter_mode,
-        );
+        let edits = Self::sync_diff_transforms(&mut snapshot, edits, DiffChangeKind::BufferEdited);
         if !edits.is_empty() {
             self.subscriptions.publish(edits);
         }
@@ -2788,7 +2649,7 @@ impl MultiBuffer {
         let mut cursor = snapshot
             .excerpts
             .cursor::<Dimensions<Option<&Locator>, ExcerptOffset>>(());
-        let mut excerpt_edits = Vec::<Edit<ExcerptOffset>>::new();
+        let mut edits = Vec::<Edit<ExcerptOffset>>::new();
 
         for locator in &locators {
             let prefix = cursor.slice(&Some(locator), Bias::Left);
@@ -2840,15 +2701,15 @@ impl MultiBuffer {
                 new: new_start_offset..new_start_offset + new_text_len,
             };
 
-            if let Some(last_edit) = excerpt_edits.last_mut() {
+            if let Some(last_edit) = edits.last_mut() {
                 if last_edit.old.end == edit.old.start {
                     last_edit.old.end = edit.old.end;
                     last_edit.new.end = edit.new.end;
                 } else {
-                    excerpt_edits.push(edit);
+                    edits.push(edit);
                 }
             } else {
-                excerpt_edits.push(edit);
+                edits.push(edit);
             }
 
             new_excerpts.push(excerpt, ());
@@ -2859,22 +2720,12 @@ impl MultiBuffer {
         new_excerpts.append(cursor.suffix(), ());
 
         drop(cursor);
-        snapshot.excerpts = new_excerpts.clone();
+        snapshot.excerpts = new_excerpts;
 
-        let edits = Self::sync_diff_transforms(
-            &mut snapshot,
-            excerpt_edits.clone(),
-            DiffChangeKind::BufferEdited,
-            self.filter_mode,
-        );
+        let edits = Self::sync_diff_transforms(&mut snapshot, edits, DiffChangeKind::BufferEdited);
         if !edits.is_empty() {
             self.subscriptions.publish(edits);
         }
-        if let Some(follower) = &self.follower {
-            follower.update(cx, |follower, cx| {
-                follower.expand_excerpts(ids.clone(), line_count, direction, cx);
-            })
-        }
         cx.emit(Event::Edited {
             edited_buffer: None,
         });
@@ -2887,11 +2738,10 @@ impl MultiBuffer {
         if !changed {
             return;
         }
-        let edits = Self::sync_from_buffer_changes(
+        let edits = Self::sync_(
             &mut self.snapshot.borrow_mut(),
             &self.buffers,
             &self.diffs,
-            self.filter_mode,
             cx,
         );
         if !edits.is_empty() {
@@ -2904,24 +2754,17 @@ impl MultiBuffer {
         if !changed {
             return;
         }
-        let edits = Self::sync_from_buffer_changes(
-            self.snapshot.get_mut(),
-            &self.buffers,
-            &self.diffs,
-            self.filter_mode,
-            cx,
-        );
+        let edits = Self::sync_(self.snapshot.get_mut(), &self.buffers, &self.diffs, cx);
 
         if !edits.is_empty() {
             self.subscriptions.publish(edits);
         }
     }
 
-    fn sync_from_buffer_changes(
+    fn sync_(
         snapshot: &mut MultiBufferSnapshot,
         buffers: &HashMap<BufferId, BufferState>,
         diffs: &HashMap<BufferId, DiffState>,
-        filter_mode: Option<MultiBufferFilterMode>,
         cx: &App,
     ) -> Vec<Edit<MultiBufferOffset>> {
         let MultiBufferSnapshot {
@@ -3044,14 +2887,13 @@ impl MultiBuffer {
 
         drop(cursor);
         *excerpts = new_excerpts;
-        Self::sync_diff_transforms(snapshot, edits, DiffChangeKind::BufferEdited, filter_mode)
+        Self::sync_diff_transforms(snapshot, edits, DiffChangeKind::BufferEdited)
     }
 
     fn sync_diff_transforms(
         snapshot: &mut MultiBufferSnapshot,
         excerpt_edits: Vec<text::Edit<ExcerptOffset>>,
         change_kind: DiffChangeKind,
-        filter_mode: Option<MultiBufferFilterMode>,
     ) -> Vec<Edit<MultiBufferOffset>> {
         if excerpt_edits.is_empty() {
             return vec![];
@@ -3068,8 +2910,8 @@ impl MultiBuffer {
         let mut at_transform_boundary = true;
         let mut end_of_current_insert = None;
 
-        let mut excerpt_edits: VecDeque<_> = excerpt_edits.into_iter().collect();
-        while let Some(edit) = excerpt_edits.pop_front() {
+        let mut excerpt_edits = excerpt_edits.into_iter().peekable();
+        while let Some(edit) = excerpt_edits.next() {
             excerpts.seek_forward(&edit.new.start, Bias::Right);
             if excerpts.item().is_none() && *excerpts.start() == edit.new.start {
                 excerpts.prev();
@@ -3090,13 +2932,7 @@ impl MultiBuffer {
             }
 
             // Compute the start of the edit in output coordinates.
-            let edit_start_overshoot = if let Some(DiffTransform::FilteredInsertedHunk { .. }) =
-                old_diff_transforms.item()
-            {
-                0
-            } else {
-                edit.old.start - old_diff_transforms.start().0
-            };
+            let edit_start_overshoot = edit.old.start - old_diff_transforms.start().0;
             let edit_old_start = old_diff_transforms.start().1 + edit_start_overshoot;
             let edit_new_start =
                 MultiBufferOffset((edit_old_start.0 as isize + output_delta) as usize);
@@ -3110,56 +2946,12 @@ impl MultiBuffer {
                 &mut old_expanded_hunks,
                 snapshot,
                 change_kind,
-                filter_mode,
             );
 
-            // When the added range of a hunk is edited, the end anchor of the hunk may be moved later
-            // in response by hunks_intersecting_range to keep it at a row boundary. In KeepDeletions
-            // mode, we need to make sure that the whole added range is still filtered out in this situation.
-            // We do that by adding an additional edit that covers the rest of the hunk added range.
-            if let Some(current_inserted_hunk) = &end_of_current_insert
-                && current_inserted_hunk.is_filtered
-                // No additional edit needed if we've already covered the whole added range.
-                && current_inserted_hunk.insertion_end_offset > edit.new.end
-                // No additional edit needed if this edit just touched the start of the hunk
-                // (this also prevents pushing the deleted region for the hunk twice).
-                && edit.new.end > current_inserted_hunk.hunk_excerpt_start
-                // No additional edit needed if there is a subsequent edit that intersects
-                // the same hunk (the last such edit will take care of it).
-                && excerpt_edits.front().is_none_or(|next_edit| {
-                    next_edit.new.start >= current_inserted_hunk.insertion_end_offset
-                })
-            {
-                let overshoot = current_inserted_hunk.insertion_end_offset - edit.new.end;
-                let additional_edit = Edit {
-                    old: edit.old.end..edit.old.end + overshoot,
-                    new: edit.new.end..current_inserted_hunk.insertion_end_offset,
-                };
-                excerpt_edits.push_front(additional_edit);
-            }
-
             // Compute the end of the edit in output coordinates.
-            let edit_old_end_overshoot = if let Some(DiffTransform::FilteredInsertedHunk {
-                ..
-            }) = old_diff_transforms.item()
-            {
-                ExcerptDimension(MultiBufferOffset(0))
-            } else {
-                ExcerptDimension(MultiBufferOffset(
-                    edit.old.end - old_diff_transforms.start().0,
-                ))
-            };
-            let edit_new_end_overshoot = if let Some(current_inserted_hunk) = &end_of_current_insert
-                && current_inserted_hunk.is_filtered
-            {
-                let insertion_end_offset = current_inserted_hunk.insertion_end_offset;
-                let excerpt_len = new_diff_transforms.summary().excerpt_len();
-                let base = insertion_end_offset.max(excerpt_len);
-                edit.new.end.saturating_sub(base)
-            } else {
-                edit.new.end - new_diff_transforms.summary().excerpt_len()
-            };
-            let edit_old_end = old_diff_transforms.start().1 + edit_old_end_overshoot.0;
+            let edit_old_end_overshoot = edit.old.end - old_diff_transforms.start().0;
+            let edit_new_end_overshoot = edit.new.end - new_diff_transforms.summary().excerpt_len();
+            let edit_old_end = old_diff_transforms.start().1 + edit_old_end_overshoot;
             let edit_new_end = new_diff_transforms.summary().output.len + edit_new_end_overshoot;
             let output_edit = Edit {
                 old: edit_old_start..edit_old_end,
@@ -3176,16 +2968,16 @@ impl MultiBuffer {
             // then recreate the content up to the end of this transform, to prepare
             // for reusing additional slices of the old transforms.
             if excerpt_edits
-                .front()
+                .peek()
                 .is_none_or(|next_edit| next_edit.old.start >= old_diff_transforms.end().0)
             {
                 let keep_next_old_transform = (old_diff_transforms.start().0 >= edit.old.end)
                     && match old_diff_transforms.item() {
-                        Some(
-                            DiffTransform::InsertedHunk { hunk_info, .. }
-                            | DiffTransform::FilteredInsertedHunk { hunk_info, .. },
-                        ) => excerpts.item().is_some_and(|excerpt| {
-                            hunk_info.hunk_start_anchor.is_valid(&excerpt.buffer)
+                        Some(DiffTransform::BufferContent {
+                            inserted_hunk_info: Some(hunk),
+                            ..
+                        }) => excerpts.item().is_some_and(|excerpt| {
+                            hunk.hunk_start_anchor.is_valid(&excerpt.buffer)
                         }),
                         _ => true,
                     };
@@ -3201,7 +2993,7 @@ impl MultiBuffer {
                     snapshot,
                     &mut new_diff_transforms,
                     excerpt_offset,
-                    end_of_current_insert.as_ref(),
+                    end_of_current_insert,
                 );
                 at_transform_boundary = true;
             }
@@ -3213,8 +3005,9 @@ impl MultiBuffer {
         // Ensure there's always at least one buffer content transform.
         if new_diff_transforms.is_empty() {
             new_diff_transforms.push(
-                DiffTransform::Unmodified {
+                DiffTransform::BufferContent {
                     summary: Default::default(),
+                    inserted_hunk_info: None,
                 },
                 (),
             );
@@ -3238,11 +3031,10 @@ impl MultiBuffer {
             Dimensions<ExcerptOffset, MultiBufferOffset>,
         >,
         new_diff_transforms: &mut SumTree<DiffTransform>,
-        end_of_current_insert: &mut Option<CurrentInsertedHunk>,
+        end_of_current_insert: &mut Option<(ExcerptOffset, DiffTransformHunkInfo)>,
         old_expanded_hunks: &mut HashSet<DiffTransformHunkInfo>,
         snapshot: &MultiBufferSnapshot,
         change_kind: DiffChangeKind,
-        filter_mode: Option<MultiBufferFilterMode>,
     ) -> bool {
         log::trace!(
             "recomputing diff transform for edit {:?} => {:?}",
@@ -3308,7 +3100,6 @@ impl MultiBuffer {
                         excerpt_id: excerpt.id,
                         hunk_start_anchor: hunk.buffer_range.start,
                         hunk_secondary_status: hunk.secondary_status,
-                        base_text_byte_range: hunk.diff_base_byte_range.clone(),
                     };
 
                     let hunk_excerpt_start = excerpt_start
@@ -3320,7 +3111,7 @@ impl MultiBuffer {
                         snapshot,
                         new_diff_transforms,
                         hunk_excerpt_start,
-                        end_of_current_insert.as_ref(),
+                        *end_of_current_insert,
                     );
 
                     // For every existing hunk, determine if it was previously expanded
@@ -3353,7 +3144,6 @@ impl MultiBuffer {
                         if !hunk.diff_base_byte_range.is_empty()
                             && hunk_buffer_range.start >= edit_buffer_start
                             && hunk_buffer_range.start <= excerpt_buffer_end
-                            && filter_mode != Some(MultiBufferFilterMode::KeepInsertions)
                         {
                             let base_text = diff.base_text();
                             let mut text_cursor =
@@ -3369,9 +3159,10 @@ impl MultiBuffer {
 
                             new_diff_transforms.push(
                                 DiffTransform::DeletedHunk {
+                                    base_text_byte_range: hunk.diff_base_byte_range.clone(),
                                     summary: base_text_summary,
                                     buffer_id: excerpt.buffer_id,
-                                    hunk_info: hunk_info.clone(),
+                                    hunk_info,
                                     has_trailing_newline,
                                 },
                                 (),
@@ -3379,15 +3170,8 @@ impl MultiBuffer {
                         }
 
                         if !hunk_buffer_range.is_empty() {
-                            let is_filtered =
-                                filter_mode == Some(MultiBufferFilterMode::KeepDeletions);
-                            let insertion_end_offset = hunk_excerpt_end.min(excerpt_end);
-                            *end_of_current_insert = Some(CurrentInsertedHunk {
-                                hunk_excerpt_start,
-                                insertion_end_offset,
-                                hunk_info,
-                                is_filtered,
-                            });
+                            *end_of_current_insert =
+                                Some((hunk_excerpt_end.min(excerpt_end), hunk_info));
                         }
                     }
                 }
@@ -3407,8 +3191,15 @@ impl MultiBuffer {
         new_transforms: &mut SumTree<DiffTransform>,
         subtree: SumTree<DiffTransform>,
     ) {
-        if let Some(transform) = subtree.first()
-            && Self::extend_last_buffer_content_transform(new_transforms, transform)
+        if let Some(DiffTransform::BufferContent {
+            inserted_hunk_info,
+            summary,
+        }) = subtree.first()
+            && Self::extend_last_buffer_content_transform(
+                new_transforms,
+                *inserted_hunk_info,
+                *summary,
+            )
         {
             let mut cursor = subtree.cursor::<()>(());
             cursor.next();
@@ -3420,7 +3211,16 @@ impl MultiBuffer {
     }
 
     fn push_diff_transform(new_transforms: &mut SumTree<DiffTransform>, transform: DiffTransform) {
-        if Self::extend_last_buffer_content_transform(new_transforms, &transform) {
+        if let DiffTransform::BufferContent {
+            inserted_hunk_info: inserted_hunk_anchor,
+            summary,
+        } = transform
+            && Self::extend_last_buffer_content_transform(
+                new_transforms,
+                inserted_hunk_anchor,
+                summary,
+            )
+        {
             return;
         }
         new_transforms.push(transform, ());
@@ -3430,56 +3230,55 @@ impl MultiBuffer {
         old_snapshot: &MultiBufferSnapshot,
         new_transforms: &mut SumTree<DiffTransform>,
         end_offset: ExcerptOffset,
-        current_inserted_hunk: Option<&CurrentInsertedHunk>,
+        current_inserted_hunk: Option<(ExcerptOffset, DiffTransformHunkInfo)>,
     ) {
-        if let Some(current_inserted_hunk) = current_inserted_hunk {
-            let start_offset = new_transforms.summary().excerpt_len();
-            let end_offset = current_inserted_hunk.insertion_end_offset.min(end_offset);
-            if end_offset > start_offset {
-                let summary_to_add = old_snapshot
-                    .text_summary_for_excerpt_offset_range::<MBTextSummary>(
-                        start_offset..end_offset,
-                    );
+        let inserted_region = current_inserted_hunk.map(|(insertion_end_offset, hunk_info)| {
+            (end_offset.min(insertion_end_offset), Some(hunk_info))
+        });
+        let unchanged_region = [(end_offset, None)];
 
-                let transform = if current_inserted_hunk.is_filtered {
-                    DiffTransform::FilteredInsertedHunk {
-                        summary: summary_to_add,
-                        hunk_info: current_inserted_hunk.hunk_info.clone(),
-                    }
-                } else {
-                    DiffTransform::InsertedHunk {
-                        summary: summary_to_add,
-                        hunk_info: current_inserted_hunk.hunk_info.clone(),
-                    }
-                };
-                if !Self::extend_last_buffer_content_transform(new_transforms, &transform) {
-                    new_transforms.push(transform, ())
-                }
+        for (end_offset, inserted_hunk_info) in inserted_region.into_iter().chain(unchanged_region)
+        {
+            let start_offset = new_transforms.summary().excerpt_len();
+            if end_offset <= start_offset {
+                continue;
             }
-        }
-
-        let start_offset = new_transforms.summary().excerpt_len();
-        if end_offset > start_offset {
             let summary_to_add = old_snapshot
                 .text_summary_for_excerpt_offset_range::<MBTextSummary>(start_offset..end_offset);
 
-            let transform = DiffTransform::Unmodified {
-                summary: summary_to_add,
-            };
-            if !Self::extend_last_buffer_content_transform(new_transforms, &transform) {
-                new_transforms.push(transform, ())
+            if !Self::extend_last_buffer_content_transform(
+                new_transforms,
+                inserted_hunk_info,
+                summary_to_add,
+            ) {
+                new_transforms.push(
+                    DiffTransform::BufferContent {
+                        summary: summary_to_add,
+                        inserted_hunk_info,
+                    },
+                    (),
+                )
             }
         }
     }
 
     fn extend_last_buffer_content_transform(
         new_transforms: &mut SumTree<DiffTransform>,
-        transform: &DiffTransform,
+        new_inserted_hunk_info: Option<DiffTransformHunkInfo>,
+        summary_to_add: MBTextSummary,
     ) -> bool {
         let mut did_extend = false;
         new_transforms.update_last(
             |last_transform| {
-                did_extend = last_transform.merge_with(&transform);
+                if let DiffTransform::BufferContent {
+                    summary,
+                    inserted_hunk_info: inserted_hunk_anchor,
+                } = last_transform
+                    && *inserted_hunk_anchor == new_inserted_hunk_info
+                {
+                    *summary += summary_to_add;
+                    did_extend = true;
+                }
             },
             (),
         );
@@ -3487,72 +3286,6 @@ impl MultiBuffer {
     }
 }
 
-impl DiffTransform {
-    /// Ergonomic wrapper for [`DiffTransform::merged_with`] that applies the
-    /// merging in-place. Returns `true` if merging was possible.
-    #[must_use = "check whether merging actually succeeded"]
-    fn merge_with(&mut self, other: &Self) -> bool {
-        match self.to_owned().merged_with(other) {
-            Some(merged) => {
-                *self = merged;
-                true
-            }
-            None => false,
-        }
-    }
-
-    /// Attempt to merge `self` with `other`, and return the merged transform.
-    ///
-    /// This will succeed if all of the following are true:
-    /// - both transforms are the same variant
-    /// - neither transform is [`DiffTransform::DeletedHunk`]
-    /// - if both transform are either [`DiffTransform::InsertedHunk`] or
-    ///   [`DiffTransform::FilteredInsertedHunk`], then their
-    ///   `hunk_info.hunk_start_anchor`s match
-    #[must_use = "check whether merging actually succeeded"]
-    #[rustfmt::skip]
-    fn merged_with(self, other: &Self) -> Option<Self> {
-        match (self, other) {
-            (
-                DiffTransform::Unmodified { mut summary },
-                DiffTransform::Unmodified { summary: other_summary },
-            ) => {
-                summary += *other_summary;
-                Some(DiffTransform::Unmodified { summary })
-            }
-            (
-                DiffTransform::FilteredInsertedHunk { mut summary, hunk_info },
-                DiffTransform::FilteredInsertedHunk {
-                    hunk_info: other_hunk_info,
-                    summary: other_summary,
-                },
-            ) => {
-                if hunk_info.hunk_start_anchor == other_hunk_info.hunk_start_anchor {
-                    summary += *other_summary;
-                    Some(DiffTransform::FilteredInsertedHunk { summary, hunk_info })
-                } else {
-                    None
-                }
-            }
-            (
-                DiffTransform::InsertedHunk { mut summary, hunk_info },
-                DiffTransform::InsertedHunk {
-                    hunk_info: other_hunk_info,
-                    summary: other_summary,
-                },
-            ) => {
-                if hunk_info.hunk_start_anchor == other_hunk_info.hunk_start_anchor {
-                    summary += *other_summary;
-                    Some(DiffTransform::InsertedHunk { summary, hunk_info })
-                } else {
-                    None
-                }
-            }
-            _ => return None,
-        }
-    }
-}
-
 fn build_excerpt_ranges(
     ranges: impl IntoIterator<Item = Range<Point>>,
     context_line_count: u32,
@@ -3875,31 +3608,11 @@ impl MultiBufferSnapshot {
             } else {
                 range.end.row + 1
             };
-
-            let word_diffs = (!hunk.base_word_diffs.is_empty()
-                || !hunk.buffer_word_diffs.is_empty())
-            .then(|| {
-                let hunk_start_offset =
-                    Anchor::in_buffer(excerpt.id, hunk.buffer_range.start).to_offset(self);
-
-                hunk.base_word_diffs
-                    .iter()
-                    .map(|diff| hunk_start_offset + diff.start..hunk_start_offset + diff.end)
-                    .chain(
-                        hunk.buffer_word_diffs
-                            .into_iter()
-                            .map(|diff| Anchor::range_in_buffer(excerpt.id, diff).to_offset(self)),
-                    )
-                    .collect()
-            })
-            .unwrap_or_default();
-
             Some(MultiBufferDiffHunk {
                 row_range: MultiBufferRow(range.start.row)..MultiBufferRow(end_row),
                 buffer_id: excerpt.buffer_id,
                 excerpt_id: excerpt.id,
                 buffer_range: hunk.buffer_range.clone(),
-                word_diffs,
                 diff_base_byte_range: BufferOffset(hunk.diff_base_byte_range.start)
                     ..BufferOffset(hunk.diff_base_byte_range.end),
                 secondary_status: hunk.secondary_status,
@@ -4804,20 +4517,19 @@ impl MultiBufferSnapshot {
         let end_overshoot = std::cmp::min(range.end, diff_transform_end) - diff_transform_start;
 
         let mut result = match first_transform {
-            DiffTransform::Unmodified { .. } | DiffTransform::InsertedHunk { .. } => {
+            DiffTransform::BufferContent { .. } => {
                 let excerpt_start = cursor.start().1 + start_overshoot;
                 let excerpt_end = cursor.start().1 + end_overshoot;
                 self.text_summary_for_excerpt_offset_range(excerpt_start..excerpt_end)
             }
-            DiffTransform::FilteredInsertedHunk { .. } => MBD::default(),
             DiffTransform::DeletedHunk {
                 buffer_id,
+                base_text_byte_range,
                 has_trailing_newline,
-                hunk_info,
                 ..
             } => {
-                let buffer_start = hunk_info.base_text_byte_range.start + start_overshoot;
-                let mut buffer_end = hunk_info.base_text_byte_range.start + end_overshoot;
+                let buffer_start = base_text_byte_range.start + start_overshoot;
+                let mut buffer_end = base_text_byte_range.start + end_overshoot;
                 let Some(base_text) = self.diffs.get(buffer_id).map(|diff| diff.base_text()) else {
                     panic!("{:?} is in non-existent deleted hunk", range.start)
                 };
@@ -4859,26 +4571,25 @@ impl MultiBufferSnapshot {
 
         let overshoot = range.end - cursor.start().0;
         let suffix = match last_transform {
-            DiffTransform::Unmodified { .. } | DiffTransform::InsertedHunk { .. } => {
+            DiffTransform::BufferContent { .. } => {
                 let end = cursor.start().1 + overshoot;
                 self.text_summary_for_excerpt_offset_range::<MBD>(cursor.start().1..end)
             }
-            DiffTransform::FilteredInsertedHunk { .. } => MBD::default(),
             DiffTransform::DeletedHunk {
+                base_text_byte_range,
                 buffer_id,
                 has_trailing_newline,
-                hunk_info,
                 ..
             } => {
-                let buffer_end = hunk_info.base_text_byte_range.start + overshoot;
+                let buffer_end = base_text_byte_range.start + overshoot;
                 let Some(base_text) = self.diffs.get(buffer_id).map(|diff| diff.base_text()) else {
                     panic!("{:?} is in non-existent deleted hunk", range.end)
                 };
 
                 let mut suffix = base_text.text_summary_for_range::<MBD::TextDimension, _>(
-                    hunk_info.base_text_byte_range.start..buffer_end,
+                    base_text_byte_range.start..buffer_end,
                 );
-                if *has_trailing_newline && buffer_end == hunk_info.base_text_byte_range.end + 1 {
+                if *has_trailing_newline && buffer_end == base_text_byte_range.end + 1 {
                     suffix.add_assign(&<MBD::TextDimension>::from_text_summary(
                         &TextSummary::from("\n"),
                     ))
@@ -4984,7 +4695,7 @@ impl MultiBufferSnapshot {
             match diff_transforms.item() {
                 Some(DiffTransform::DeletedHunk {
                     buffer_id,
-                    hunk_info,
+                    base_text_byte_range,
                     ..
                 }) => {
                     if let Some(diff_base_anchor) = &anchor.diff_base_anchor
@@ -4993,12 +4704,12 @@ impl MultiBufferSnapshot {
                         && base_text.can_resolve(diff_base_anchor)
                     {
                         let base_text_offset = diff_base_anchor.to_offset(base_text);
-                        if base_text_offset >= hunk_info.base_text_byte_range.start
-                            && base_text_offset <= hunk_info.base_text_byte_range.end
+                        if base_text_offset >= base_text_byte_range.start
+                            && base_text_offset <= base_text_byte_range.end
                         {
                             let position_in_hunk = base_text
                                 .text_summary_for_range::<MBD::TextDimension, _>(
-                                    hunk_info.base_text_byte_range.start..base_text_offset,
+                                    base_text_byte_range.start..base_text_offset,
                                 );
                             position.0.add_text_dim(&position_in_hunk);
                         } else if at_transform_end {
@@ -5012,14 +4723,8 @@ impl MultiBufferSnapshot {
                         diff_transforms.next();
                         continue;
                     }
-
-                    if !matches!(
-                        diff_transforms.item(),
-                        Some(DiffTransform::FilteredInsertedHunk { .. })
-                    ) {
-                        let overshoot = excerpt_position - diff_transforms.start().0;
-                        position += overshoot;
-                    }
+                    let overshoot = excerpt_position - diff_transforms.start().0;
+                    position += overshoot;
                 }
             }
 
@@ -5309,12 +5014,11 @@ impl MultiBufferSnapshot {
         let mut diff_base_anchor = None;
         if let Some(DiffTransform::DeletedHunk {
             buffer_id,
+            base_text_byte_range,
             has_trailing_newline,
-            hunk_info,
             ..
         }) = diff_transforms.item()
         {
-            let base_text_byte_range = &hunk_info.base_text_byte_range;
             let diff = self.diffs.get(buffer_id).expect("missing diff");
             if offset_in_transform > base_text_byte_range.len() {
                 debug_assert!(*has_trailing_newline);