diff --git a/crates/editor/src/multi_buffer.rs b/crates/editor/src/multi_buffer.rs index 309712432a..a03af9d10a 100644 --- a/crates/editor/src/multi_buffer.rs +++ b/crates/editor/src/multi_buffer.rs @@ -589,6 +589,18 @@ impl MultiBuffer { props: ExcerptProperties, cx: &mut ModelContext, ) -> ExcerptId + where + O: text::ToOffset, + { + self.insert_excerpt_after(&ExcerptId::max(), props, cx) + } + + pub fn insert_excerpt_after( + &mut self, + prev_excerpt_id: &ExcerptId, + props: ExcerptProperties, + cx: &mut ModelContext, + ) -> ExcerptId where O: text::ToOffset, { @@ -599,19 +611,28 @@ impl MultiBuffer { let range = buffer_snapshot.anchor_before(&props.range.start) ..buffer_snapshot.anchor_after(&props.range.end); let mut snapshot = self.snapshot.borrow_mut(); - let mut prev_id = None; - let edit_start = snapshot.excerpts.summary().text.bytes; - snapshot.excerpts.update_last( + let mut cursor = snapshot.excerpts.cursor::>(); + let mut new_excerpts = cursor.slice(&Some(prev_excerpt_id), Bias::Right, &()); + + let mut prev_id = ExcerptId::min(); + let edit_start = new_excerpts.summary().text.bytes; + new_excerpts.update_last( |excerpt| { excerpt.has_trailing_newline = true; - prev_id = Some(excerpt.id.clone()); + prev_id = excerpt.id.clone(); }, &(), ); - let id = ExcerptId::between(&prev_id.unwrap_or(ExcerptId::min()), &ExcerptId::max()); - self.buffers - .borrow_mut() + let mut next_id = ExcerptId::max(); + if let Some(next_excerpt) = cursor.item() { + next_id = next_excerpt.id.clone(); + } + + let id = ExcerptId::between(&prev_id, &next_id); + + let mut buffers = self.buffers.borrow_mut(); + let buffer_state = buffers .entry(props.buffer.id()) .or_insert_with(|| BufferState { last_version: buffer_snapshot.version().clone(), @@ -623,14 +644,28 @@ impl MultiBuffer { cx.subscribe(&props.buffer, Self::on_buffer_event), ], buffer: props.buffer.clone(), - }) - .excerpts - .push(id.clone()); - let excerpt = Excerpt::new(id.clone(), props.buffer.id(), buffer_snapshot, range, false); - snapshot.excerpts.push(excerpt, &()); + }); + if let Err(ix) = buffer_state.excerpts.binary_search(&id) { + buffer_state.excerpts.insert(ix, id.clone()); + } + + let excerpt = Excerpt::new( + id.clone(), + props.buffer.id(), + buffer_snapshot, + range, + cursor.item().is_some(), + ); + new_excerpts.push(excerpt, &()); + let edit_end = new_excerpts.summary().text.bytes; + + new_excerpts.push_tree(cursor.suffix(&()), &()); + drop(cursor); + snapshot.excerpts = new_excerpts; + self.subscriptions.publish_mut([Edit { old: edit_start..edit_start, - new: edit_start..snapshot.excerpts.summary().text.bytes, + new: edit_start..edit_end, }]); cx.notify(); @@ -2302,8 +2337,17 @@ mod tests { let end_ix = buffer.clip_offset(rng.gen_range(0..=buffer.len()), Bias::Right); let start_ix = buffer.clip_offset(rng.gen_range(0..=end_ix), Bias::Left); let anchor_range = buffer.anchor_before(start_ix)..buffer.anchor_after(end_ix); + let prev_excerpt_ix = rng.gen_range(0..=expected_excerpts.len()); + let prev_excerpt_id = excerpt_ids + .get(prev_excerpt_ix) + .cloned() + .unwrap_or(ExcerptId::max()); + let excerpt_ix = (prev_excerpt_ix + 1).min(expected_excerpts.len()); + log::info!( - "Pushing excerpt for buffer {}: {:?}[{:?}] = {:?}", + "Inserting excerpt at {} of {} for buffer {}: {:?}[{:?}] = {:?}", + excerpt_ix, + expected_excerpts.len(), buffer_handle.id(), buffer.text(), start_ix..end_ix, @@ -2311,7 +2355,8 @@ mod tests { ); let excerpt_id = list.update(cx, |list, cx| { - list.push_excerpt( + list.insert_excerpt_after( + &prev_excerpt_id, ExcerptProperties { buffer: &buffer_handle, range: start_ix..end_ix, @@ -2319,8 +2364,9 @@ mod tests { cx, ) }); - excerpt_ids.push(excerpt_id); - expected_excerpts.push((buffer_handle.clone(), anchor_range)); + + excerpt_ids.insert(excerpt_ix, excerpt_id); + expected_excerpts.insert(excerpt_ix, (buffer_handle.clone(), anchor_range)); } }