@@ -64,17 +64,22 @@ pub struct MultiBuffer {
/// Use [`MultiBuffer::snapshot`] to get a up-to-date snapshot.
snapshot: RefCell<MultiBufferSnapshot>,
/// Contains the state of the buffers being edited
- buffers: RefCell<HashMap<BufferId, BufferState>>,
- // only used by consumers using `set_excerpts_for_buffer`
+ buffers: HashMap<BufferId, BufferState>,
+ /// Mapping from path keys to their excerpts.
excerpts_by_path: BTreeMap<PathKey, Vec<ExcerptId>>,
+ /// Mapping from excerpt IDs to their path key.
paths_by_excerpt: HashMap<ExcerptId, PathKey>,
+ /// Mapping from buffer IDs to their diff states
diffs: HashMap<BufferId, DiffState>,
- // all_diff_hunks_expanded: bool,
subscriptions: Topic,
/// If true, the multi-buffer only contains a single [`Buffer`] and a single [`Excerpt`]
singleton: bool,
+ /// The history of the multi-buffer.
history: History,
+ /// The explicit title of the multi-buffer.
+ /// If `None`, it will be derived from the underlying path or content.
title: Option<String>,
+ /// The writing capability of the multi-buffer.
capability: Capability,
buffer_changed_since_sync: Rc<Cell<bool>>,
}
@@ -249,8 +254,8 @@ pub trait ToPointUtf16: 'static + fmt::Debug {
struct BufferState {
buffer: Entity<Buffer>,
- last_version: clock::Global,
- last_non_text_state_update_count: usize,
+ last_version: RefCell<clock::Global>,
+ last_non_text_state_update_count: Cell<usize>,
excerpts: Vec<Locator>,
_subscriptions: [gpui::Subscription; 2],
}
@@ -282,15 +287,20 @@ impl DiffState {
#[derive(Clone, Default)]
pub struct MultiBufferSnapshot {
singleton: bool,
+ /* mut */
excerpts: SumTree<Excerpt>,
+ /* mut */
excerpt_ids: SumTree<ExcerptIdMapping>,
diffs: TreeMap<BufferId, BufferDiffSnapshot>,
diff_transforms: SumTree<DiffTransform>,
+ /* mut */
replaced_excerpts: TreeMap<ExcerptId, ExcerptId>,
+ /* mut */
trailing_excerpt_update_count: usize,
all_diff_hunks_expanded: bool,
non_text_state_update_count: usize,
edit_count: usize,
+ /* mut */
is_dirty: bool,
has_deleted_file: bool,
has_conflict: bool,
@@ -612,12 +622,41 @@ impl IndentGuide {
impl MultiBuffer {
pub fn new(capability: Capability) -> Self {
- Self {
- snapshot: RefCell::new(MultiBufferSnapshot {
+ Self::new_(
+ capability,
+ MultiBufferSnapshot {
show_headers: true,
..MultiBufferSnapshot::default()
- }),
- buffers: RefCell::default(),
+ },
+ )
+ }
+
+ pub fn without_headers(capability: Capability) -> Self {
+ Self::new_(capability, Default::default())
+ }
+
+ pub fn singleton(buffer: Entity<Buffer>, cx: &mut Context<Self>) -> Self {
+ let mut this = Self::new_(
+ buffer.read(cx).capability(),
+ MultiBufferSnapshot {
+ singleton: true,
+ ..MultiBufferSnapshot::default()
+ },
+ );
+ this.singleton = true;
+ this.push_excerpts(
+ buffer,
+ [ExcerptRange::new(text::Anchor::MIN..text::Anchor::MAX)],
+ cx,
+ );
+ this
+ }
+
+ #[inline]
+ pub fn new_(capability: Capability, snapshot: MultiBufferSnapshot) -> Self {
+ Self {
+ snapshot: RefCell::new(snapshot),
+ buffers: Default::default(),
diffs: HashMap::default(),
subscriptions: Topic::default(),
singleton: false,
@@ -636,32 +675,10 @@ impl MultiBuffer {
}
}
- pub fn without_headers(capability: Capability) -> Self {
- Self {
- snapshot: Default::default(),
- buffers: Default::default(),
- excerpts_by_path: Default::default(),
- paths_by_excerpt: Default::default(),
- diffs: HashMap::default(),
- subscriptions: Default::default(),
- singleton: false,
- capability,
- buffer_changed_since_sync: Default::default(),
- history: History {
- next_transaction_id: Default::default(),
- undo_stack: Default::default(),
- redo_stack: Default::default(),
- transaction_depth: 0,
- group_interval: Duration::from_millis(300),
- },
- title: Default::default(),
- }
- }
-
pub fn clone(&self, new_cx: &mut Context<Self>) -> Self {
let mut buffers = HashMap::default();
let buffer_changed_since_sync = Rc::new(Cell::new(false));
- for (buffer_id, buffer_state) in self.buffers.borrow().iter() {
+ for (buffer_id, buffer_state) in self.buffers.iter() {
buffer_state.buffer.update(new_cx, |buffer, _| {
buffer.record_changes(Rc::downgrade(&buffer_changed_since_sync));
});
@@ -670,7 +687,9 @@ impl MultiBuffer {
BufferState {
buffer: buffer_state.buffer.clone(),
last_version: buffer_state.last_version.clone(),
- last_non_text_state_update_count: buffer_state.last_non_text_state_update_count,
+ last_non_text_state_update_count: buffer_state
+ .last_non_text_state_update_count
+ .clone(),
excerpts: buffer_state.excerpts.clone(),
_subscriptions: [
new_cx.observe(&buffer_state.buffer, |_, _, cx| cx.notify()),
@@ -685,7 +704,7 @@ impl MultiBuffer {
}
Self {
snapshot: RefCell::new(self.snapshot.borrow().clone()),
- buffers: RefCell::new(buffers),
+ buffers: buffers,
excerpts_by_path: Default::default(),
paths_by_excerpt: Default::default(),
diffs: diff_bases,
@@ -707,18 +726,6 @@ impl MultiBuffer {
self.capability == Capability::ReadOnly
}
- pub fn singleton(buffer: Entity<Buffer>, cx: &mut Context<Self>) -> Self {
- let mut this = Self::new(buffer.read(cx).capability());
- this.singleton = true;
- this.push_excerpts(
- buffer,
- [ExcerptRange::new(text::Anchor::MIN..text::Anchor::MAX)],
- cx,
- );
- this.snapshot.borrow_mut().singleton = true;
- this
- }
-
/// Returns an up-to-date snapshot of the MultiBuffer.
pub fn snapshot(&self, cx: &App) -> MultiBufferSnapshot {
self.sync(cx);
@@ -732,15 +739,7 @@ impl MultiBuffer {
pub fn as_singleton(&self) -> Option<Entity<Buffer>> {
if self.singleton {
- Some(
- self.buffers
- .borrow()
- .values()
- .next()
- .unwrap()
- .buffer
- .clone(),
- )
+ Some(self.buffers.values().next().unwrap().buffer.clone())
} else {
None
}
@@ -773,7 +772,7 @@ impl MultiBuffer {
}
pub fn is_empty(&self) -> bool {
- self.buffers.borrow().is_empty()
+ self.buffers.is_empty()
}
pub fn symbols_containing<T: ToOffset>(
@@ -817,7 +816,7 @@ impl MultiBuffer {
mut autoindent_mode: Option<AutoindentMode>,
cx: &mut Context<MultiBuffer>,
) {
- if this.read_only() || this.buffers.borrow().is_empty() {
+ if this.read_only() || this.buffers.is_empty() {
return;
}
@@ -836,78 +835,74 @@ impl MultiBuffer {
for (buffer_id, mut edits) in buffer_edits {
buffer_ids.push(buffer_id);
edits.sort_by_key(|edit| edit.range.start);
- this.buffers.borrow()[&buffer_id]
- .buffer
- .update(cx, |buffer, cx| {
- let mut edits = edits.into_iter().peekable();
- let mut insertions = Vec::new();
- let mut original_indent_columns = Vec::new();
- let mut deletions = Vec::new();
- let empty_str: Arc<str> = Arc::default();
+ this.buffers[&buffer_id].buffer.update(cx, |buffer, cx| {
+ let mut edits = edits.into_iter().peekable();
+ let mut insertions = Vec::new();
+ let mut original_indent_columns = Vec::new();
+ let mut deletions = Vec::new();
+ let empty_str: Arc<str> = Arc::default();
+ while let Some(BufferEdit {
+ mut range,
+ mut new_text,
+ mut is_insertion,
+ original_indent_column,
+ excerpt_id,
+ }) = edits.next()
+ {
while let Some(BufferEdit {
- mut range,
- mut new_text,
- mut is_insertion,
- original_indent_column,
- excerpt_id,
- }) = edits.next()
+ range: next_range,
+ is_insertion: next_is_insertion,
+ new_text: next_new_text,
+ excerpt_id: next_excerpt_id,
+ ..
+ }) = edits.peek()
{
- while let Some(BufferEdit {
- range: next_range,
- is_insertion: next_is_insertion,
- new_text: next_new_text,
- excerpt_id: next_excerpt_id,
- ..
- }) = edits.peek()
- {
- if range.end >= next_range.start {
- range.end = cmp::max(next_range.end, range.end);
- is_insertion |= *next_is_insertion;
- if excerpt_id == *next_excerpt_id {
- new_text = format!("{new_text}{next_new_text}").into();
- }
- edits.next();
- } else {
- break;
+ if range.end >= next_range.start {
+ range.end = cmp::max(next_range.end, range.end);
+ is_insertion |= *next_is_insertion;
+ if excerpt_id == *next_excerpt_id {
+ new_text = format!("{new_text}{next_new_text}").into();
}
+ edits.next();
+ } else {
+ break;
}
+ }
- if is_insertion {
- original_indent_columns.push(original_indent_column);
- insertions.push((
- buffer.anchor_before(range.start)
- ..buffer.anchor_before(range.end),
- new_text.clone(),
- ));
- } else if !range.is_empty() {
- deletions.push((
- buffer.anchor_before(range.start)
- ..buffer.anchor_before(range.end),
- empty_str.clone(),
- ));
- }
+ if is_insertion {
+ original_indent_columns.push(original_indent_column);
+ insertions.push((
+ buffer.anchor_before(range.start)..buffer.anchor_before(range.end),
+ new_text.clone(),
+ ));
+ } else if !range.is_empty() {
+ deletions.push((
+ buffer.anchor_before(range.start)..buffer.anchor_before(range.end),
+ empty_str.clone(),
+ ));
}
+ }
- let deletion_autoindent_mode =
- if let Some(AutoindentMode::Block { .. }) = autoindent_mode {
- Some(AutoindentMode::Block {
- original_indent_columns: Default::default(),
- })
- } else {
- autoindent_mode.clone()
- };
- let insertion_autoindent_mode =
- if let Some(AutoindentMode::Block { .. }) = autoindent_mode {
- Some(AutoindentMode::Block {
- original_indent_columns,
- })
- } else {
- autoindent_mode.clone()
- };
+ let deletion_autoindent_mode =
+ if let Some(AutoindentMode::Block { .. }) = autoindent_mode {
+ Some(AutoindentMode::Block {
+ original_indent_columns: Default::default(),
+ })
+ } else {
+ autoindent_mode.clone()
+ };
+ let insertion_autoindent_mode =
+ if let Some(AutoindentMode::Block { .. }) = autoindent_mode {
+ Some(AutoindentMode::Block {
+ original_indent_columns,
+ })
+ } else {
+ autoindent_mode.clone()
+ };
- buffer.edit(deletions, deletion_autoindent_mode, cx);
- buffer.edit(insertions, insertion_autoindent_mode, cx);
- })
+ buffer.edit(deletions, deletion_autoindent_mode, cx);
+ buffer.edit(insertions, insertion_autoindent_mode, cx);
+ })
}
cx.emit(Event::ExcerptsEdited {
@@ -1064,7 +1059,7 @@ impl MultiBuffer {
edits: Vec<(Range<usize>, Arc<str>)>,
cx: &mut Context<MultiBuffer>,
) {
- if this.read_only() || this.buffers.borrow().is_empty() {
+ if this.read_only() || this.buffers.is_empty() {
return;
}
@@ -1088,11 +1083,9 @@ impl MultiBuffer {
ranges.push(edit.range);
}
- this.buffers.borrow()[&buffer_id]
- .buffer
- .update(cx, |buffer, cx| {
- buffer.autoindent_ranges(ranges, cx);
- })
+ this.buffers[&buffer_id].buffer.update(cx, |buffer, cx| {
+ buffer.autoindent_ranges(ranges, cx);
+ })
}
cx.emit(Event::ExcerptsEdited {
@@ -1135,7 +1128,7 @@ impl MultiBuffer {
return buffer.update(cx, |buffer, _| buffer.start_transaction_at(now));
}
- for BufferState { buffer, .. } in self.buffers.borrow().values() {
+ for BufferState { buffer, .. } in self.buffers.values() {
buffer.update(cx, |buffer, _| buffer.start_transaction_at(now));
}
self.history.start_transaction(now)
@@ -1167,7 +1160,7 @@ impl MultiBuffer {
}
let mut buffer_transactions = HashMap::default();
- for BufferState { buffer, .. } in self.buffers.borrow().values() {
+ for BufferState { buffer, .. } in self.buffers.values() {
if let Some(transaction_id) =
buffer.update(cx, |buffer, cx| buffer.end_transaction_at(now, cx))
{
@@ -1197,11 +1190,10 @@ impl MultiBuffer {
let mut ranges = Vec::new();
let snapshot = self.read(cx);
- let buffers = self.buffers.borrow();
let mut cursor = snapshot.excerpts.cursor::<ExcerptSummary>(());
for (buffer_id, buffer_transaction) in &transaction.buffer_transactions {
- let Some(buffer_state) = buffers.get(buffer_id) else {
+ let Some(buffer_state) = self.buffers.get(buffer_id) else {
continue;
};
@@ -1254,7 +1246,7 @@ impl MultiBuffer {
if let Some(destination_buffer_transaction_id) =
destination.buffer_transactions.get(&buffer_id)
{
- if let Some(state) = self.buffers.borrow().get(&buffer_id) {
+ if let Some(state) = self.buffers.get(&buffer_id) {
state.buffer.update(cx, |buffer, _| {
buffer.merge_transactions(
buffer_transaction_id,
@@ -1273,7 +1265,7 @@ impl MultiBuffer {
pub fn finalize_last_transaction(&mut self, cx: &mut Context<Self>) {
self.history.finalize_last_transaction();
- for BufferState { buffer, .. } in self.buffers.borrow().values() {
+ for BufferState { buffer, .. } in self.buffers.values() {
buffer.update(cx, |buffer, _| {
buffer.finalize_last_transaction();
});
@@ -1345,7 +1337,7 @@ impl MultiBuffer {
}
}
- for (buffer_id, buffer_state) in self.buffers.borrow().iter() {
+ for (buffer_id, buffer_state) in self.buffers.iter() {
if !selections_by_buffer.contains_key(buffer_id) {
buffer_state
.buffer
@@ -1354,32 +1346,30 @@ impl MultiBuffer {
}
for (buffer_id, mut selections) in selections_by_buffer {
- self.buffers.borrow()[&buffer_id]
- .buffer
- .update(cx, |buffer, cx| {
- selections.sort_unstable_by(|a, b| a.start.cmp(&b.start, buffer));
- let mut selections = selections.into_iter().peekable();
- let merged_selections = Arc::from_iter(iter::from_fn(|| {
- let mut selection = selections.next()?;
- while let Some(next_selection) = selections.peek() {
- if selection.end.cmp(&next_selection.start, buffer).is_ge() {
- let next_selection = selections.next().unwrap();
- if next_selection.end.cmp(&selection.end, buffer).is_ge() {
- selection.end = next_selection.end;
- }
- } else {
- break;
+ self.buffers[&buffer_id].buffer.update(cx, |buffer, cx| {
+ selections.sort_unstable_by(|a, b| a.start.cmp(&b.start, buffer));
+ let mut selections = selections.into_iter().peekable();
+ let merged_selections = Arc::from_iter(iter::from_fn(|| {
+ let mut selection = selections.next()?;
+ while let Some(next_selection) = selections.peek() {
+ if selection.end.cmp(&next_selection.start, buffer).is_ge() {
+ let next_selection = selections.next().unwrap();
+ if next_selection.end.cmp(&selection.end, buffer).is_ge() {
+ selection.end = next_selection.end;
}
+ } else {
+ break;
}
- Some(selection)
- }));
- buffer.set_active_selections(merged_selections, line_mode, cursor_shape, cx);
- });
+ }
+ Some(selection)
+ }));
+ buffer.set_active_selections(merged_selections, line_mode, cursor_shape, cx);
+ });
}
}
pub fn remove_active_selections(&self, cx: &mut Context<Self>) {
- for buffer in self.buffers.borrow().values() {
+ for buffer in self.buffers.values() {
buffer
.buffer
.update(cx, |buffer, cx| buffer.remove_active_selections(cx));
@@ -1394,7 +1384,7 @@ impl MultiBuffer {
while let Some(transaction) = self.history.pop_undo() {
let mut undone = false;
for (buffer_id, buffer_transaction_id) in &mut transaction.buffer_transactions {
- if let Some(BufferState { buffer, .. }) = self.buffers.borrow().get(buffer_id) {
+ if let Some(BufferState { buffer, .. }) = self.buffers.get(buffer_id) {
undone |= buffer.update(cx, |buffer, cx| {
let undo_to = *buffer_transaction_id;
if let Some(entry) = buffer.peek_undo_stack() {
@@ -1427,7 +1417,7 @@ impl MultiBuffer {
while let Some(transaction) = self.history.pop_redo() {
let mut redone = false;
for (buffer_id, buffer_transaction_id) in &mut transaction.buffer_transactions {
- if let Some(BufferState { buffer, .. }) = self.buffers.borrow().get(buffer_id) {
+ if let Some(BufferState { buffer, .. }) = self.buffers.get(buffer_id) {
redone |= buffer.update(cx, |buffer, cx| {
let redo_to = *buffer_transaction_id;
if let Some(entry) = buffer.peek_redo_stack() {
@@ -1451,7 +1441,7 @@ impl MultiBuffer {
buffer.update(cx, |buffer, cx| buffer.undo_transaction(transaction_id, cx));
} else if let Some(transaction) = self.history.remove_from_undo(transaction_id) {
for (buffer_id, transaction_id) in &transaction.buffer_transactions {
- if let Some(BufferState { buffer, .. }) = self.buffers.borrow().get(buffer_id) {
+ if let Some(BufferState { buffer, .. }) = self.buffers.get(buffer_id) {
buffer.update(cx, |buffer, cx| {
buffer.undo_transaction(*transaction_id, cx)
});
@@ -1467,7 +1457,7 @@ impl MultiBuffer {
});
} else if let Some(transaction) = self.history.forget(transaction_id) {
for (buffer_id, buffer_transaction_id) in transaction.buffer_transactions {
- if let Some(state) = self.buffers.borrow_mut().get_mut(&buffer_id) {
+ if let Some(state) = self.buffers.get_mut(&buffer_id) {
state.buffer.update(cx, |buffer, _| {
buffer.forget_transaction(buffer_transaction_id);
});
@@ -1571,12 +1561,7 @@ impl MultiBuffer {
continue;
};
- let Some(buffer) = self
- .buffers
- .borrow()
- .get(buffer_id)
- .map(|b| b.buffer.clone())
- else {
+ let Some(buffer) = self.buffers.get(buffer_id).map(|b| b.buffer.clone()) else {
continue;
};
@@ -1631,13 +1616,13 @@ impl MultiBuffer {
pub fn set_anchored_excerpts_for_path(
&self,
+ path_key: PathKey,
buffer: Entity<Buffer>,
ranges: Vec<Range<text::Anchor>>,
context_line_count: u32,
cx: &mut Context<Self>,
) -> Task<Vec<Range<Anchor>>> {
let buffer_snapshot = buffer.read(cx).snapshot();
- let path_key = PathKey::for_buffer(&buffer, cx);
cx.spawn(async move |multi_buffer, cx| {
let snapshot = buffer_snapshot.clone();
let (excerpt_ranges, new, counts) = cx
@@ -1802,7 +1787,7 @@ impl MultiBuffer {
last.context.end = last.context.end.max(existing_range.end);
to_remove.push(*existing_id);
self.snapshot
- .borrow_mut()
+ .get_mut()
.replaced_excerpts
.insert(*existing_id, *last_id);
existing_iter.next();
@@ -1852,7 +1837,7 @@ impl MultiBuffer {
let existing_id = existing_iter.next().unwrap();
let new_id = next_excerpt_id();
self.snapshot
- .borrow_mut()
+ .get_mut()
.replaced_excerpts
.insert(existing_id, new_id);
to_remove.push(existing_id);
@@ -1941,15 +1926,16 @@ impl MultiBuffer {
let buffer_snapshot = buffer.read(cx).snapshot();
let buffer_id = buffer_snapshot.remote_id();
- let mut buffers = self.buffers.borrow_mut();
- let buffer_state = buffers.entry(buffer_id).or_insert_with(|| {
+ let buffer_state = self.buffers.entry(buffer_id).or_insert_with(|| {
self.buffer_changed_since_sync.replace(true);
buffer.update(cx, |buffer, _| {
buffer.record_changes(Rc::downgrade(&self.buffer_changed_since_sync));
});
BufferState {
- last_version: buffer_snapshot.version().clone(),
- last_non_text_state_update_count: buffer_snapshot.non_text_state_update_count(),
+ last_version: RefCell::new(buffer_snapshot.version().clone()),
+ last_non_text_state_update_count: Cell::new(
+ buffer_snapshot.non_text_state_update_count(),
+ ),
excerpts: Default::default(),
_subscriptions: [
cx.observe(&buffer, |_, _, cx| cx.notify()),
@@ -1959,7 +1945,7 @@ impl MultiBuffer {
}
});
- let mut snapshot = self.snapshot.borrow_mut();
+ let mut snapshot = self.snapshot.get_mut();
let mut prev_locator = snapshot.excerpt_locator_for_id(prev_excerpt_id).clone();
let mut new_excerpt_ids = mem::take(&mut snapshot.excerpt_ids);
@@ -2023,7 +2009,7 @@ impl MultiBuffer {
snapshot.trailing_excerpt_update_count += 1;
}
- self.sync_diff_transforms(
+ let edits = Self::sync_diff_transforms(
&mut snapshot,
vec![Edit {
old: edit_start..edit_start,
@@ -2031,6 +2017,10 @@ impl MultiBuffer {
}],
DiffChangeKind::BufferEdited,
);
+ if !edits.is_empty() {
+ self.subscriptions.publish(edits);
+ }
+
cx.emit(Event::Edited {
edited_buffer: None,
});
@@ -2045,15 +2035,10 @@ impl MultiBuffer {
pub fn clear(&mut self, cx: &mut Context<Self>) {
self.sync(cx);
let ids = self.excerpt_ids();
- let removed_buffer_ids = self
- .buffers
- .borrow_mut()
- .drain()
- .map(|(id, _)| id)
- .collect();
+ let removed_buffer_ids = self.buffers.drain().map(|(id, _)| id).collect();
self.excerpts_by_path.clear();
self.paths_by_excerpt.clear();
- let mut snapshot = self.snapshot.borrow_mut();
+ let mut snapshot = self.snapshot.get_mut();
let start = ExcerptOffset::new(0);
let prev_len = ExcerptOffset::new(snapshot.excerpts.summary().text.len);
snapshot.excerpts = Default::default();
@@ -2063,7 +2048,7 @@ impl MultiBuffer {
snapshot.has_conflict = false;
snapshot.replaced_excerpts.clear();
- self.sync_diff_transforms(
+ let edits = Self::sync_diff_transforms(
&mut snapshot,
vec![Edit {
old: start..prev_len,
@@ -2071,6 +2056,9 @@ impl MultiBuffer {
}],
DiffChangeKind::BufferEdited,
);
+ if !edits.is_empty() {
+ self.subscriptions.publish(edits);
+ }
cx.emit(Event::Edited {
edited_buffer: None,
});
@@ -2088,9 +2076,8 @@ impl MultiBuffer {
) -> Vec<(ExcerptId, ExcerptRange<text::Anchor>)> {
let mut excerpts = Vec::new();
let snapshot = self.read(cx);
- let buffers = self.buffers.borrow();
let mut cursor = snapshot.excerpts.cursor::<Option<&Locator>>(());
- if let Some(locators) = buffers.get(&buffer_id).map(|state| &state.excerpts) {
+ if let Some(locators) = self.buffers.get(&buffer_id).map(|state| &state.excerpts) {
for locator in locators {
cursor.seek_forward(&Some(locator), Bias::Left);
if let Some(excerpt) = cursor.item()
@@ -2106,7 +2093,6 @@ impl MultiBuffer {
pub fn excerpt_ranges_for_buffer(&self, buffer_id: BufferId, cx: &App) -> Vec<Range<Point>> {
let snapshot = self.read(cx);
- let buffers = self.buffers.borrow();
let mut excerpts = snapshot
.excerpts
.cursor::<Dimensions<Option<&Locator>, ExcerptDimension<Point>>>(());
@@ -2114,7 +2100,8 @@ impl MultiBuffer {
.diff_transforms
.cursor::<Dimensions<ExcerptDimension<Point>, OutputDimension<Point>>>(());
diff_transforms.next();
- let locators = buffers
+ let locators = self
+ .buffers
.get(&buffer_id)
.into_iter()
.flat_map(|state| &state.excerpts);
@@ -2175,12 +2162,7 @@ impl MultiBuffer {
.map(|excerpt| {
(
excerpt.id,
- self.buffers
- .borrow()
- .get(&excerpt.buffer_id)
- .unwrap()
- .buffer
- .clone(),
+ self.buffers.get(&excerpt.buffer_id).unwrap().buffer.clone(),
excerpt.range.context.clone(),
)
})
@@ -2204,11 +2186,7 @@ impl MultiBuffer {
let snapshot = self.read(cx);
let (buffer, offset) = snapshot.point_to_buffer_offset(point)?;
Some((
- self.buffers
- .borrow()
- .get(&buffer.remote_id())?
- .buffer
- .clone(),
+ self.buffers.get(&buffer.remote_id())?.buffer.clone(),
offset,
))
}
@@ -2223,11 +2201,7 @@ impl MultiBuffer {
let (buffer, point, is_main_buffer) =
snapshot.point_to_buffer_point(point.to_point(&snapshot))?;
Some((
- self.buffers
- .borrow()
- .get(&buffer.remote_id())?
- .buffer
- .clone(),
+ self.buffers.get(&buffer.remote_id())?.buffer.clone(),
point,
is_main_buffer,
))
@@ -2273,8 +2247,7 @@ impl MultiBuffer {
return;
}
- let mut buffers = self.buffers.borrow_mut();
- let mut snapshot = self.snapshot.borrow_mut();
+ let mut snapshot = self.snapshot.get_mut();
let mut new_excerpts = SumTree::default();
let mut cursor = snapshot
.excerpts
@@ -2297,14 +2270,14 @@ impl MultiBuffer {
// Skip over the removed excerpt.
'remove_excerpts: loop {
- if let Some(buffer_state) = buffers.get_mut(&excerpt.buffer_id) {
+ if let Some(buffer_state) = self.buffers.get_mut(&excerpt.buffer_id) {
buffer_state.excerpts.retain(|l| l != &excerpt.locator);
if buffer_state.excerpts.is_empty() {
log::debug!(
"removing buffer and diff for buffer {}",
excerpt.buffer_id
);
- buffers.remove(&excerpt.buffer_id);
+ self.buffers.remove(&excerpt.buffer_id);
removed_buffer_ids.push(excerpt.buffer_id);
}
}
@@ -2355,7 +2328,10 @@ impl MultiBuffer {
snapshot.trailing_excerpt_update_count += 1;
}
- self.sync_diff_transforms(&mut snapshot, edits, DiffChangeKind::BufferEdited);
+ let edits = Self::sync_diff_transforms(&mut snapshot, edits, DiffChangeKind::BufferEdited);
+ if !edits.is_empty() {
+ self.subscriptions.publish(edits);
+ }
self.buffer_changed_since_sync.replace(true);
cx.emit(Event::Edited {
edited_buffer: None,
@@ -2372,12 +2348,11 @@ impl MultiBuffer {
anchors: Anchors,
cx: &mut Context<Self>,
) -> impl 'static + Future<Output = Result<()>> + use<Anchors> {
- let borrow = self.buffers.borrow();
let mut error = None;
let mut futures = Vec::new();
for anchor in anchors {
if let Some(buffer_id) = anchor.buffer_id {
- if let Some(buffer) = borrow.get(&buffer_id) {
+ if let Some(buffer) = self.buffers.get(&buffer_id) {
buffer.buffer.update(cx, |buffer, _| {
futures.push(buffer.wait_for_anchors([anchor.text_anchor]))
});
@@ -2407,12 +2382,7 @@ impl MultiBuffer {
) -> Option<(Entity<Buffer>, language::Anchor)> {
let snapshot = self.read(cx);
let anchor = snapshot.anchor_before(position);
- let buffer = self
- .buffers
- .borrow()
- .get(&anchor.buffer_id?)?
- .buffer
- .clone();
+ let buffer = self.buffers.get(&anchor.buffer_id?)?.buffer.clone();
Some((buffer, anchor.text_anchor))
}
@@ -2444,7 +2414,7 @@ impl MultiBuffer {
fn buffer_diff_language_changed(&mut self, diff: Entity<BufferDiff>, cx: &mut Context<Self>) {
self.sync(cx);
- let mut snapshot = self.snapshot.borrow_mut();
+ let snapshot = self.snapshot.get_mut();
let diff = diff.read(cx);
let buffer_id = diff.buffer_id;
let diff = diff.snapshot(cx);
@@ -2462,8 +2432,7 @@ impl MultiBuffer {
let diff = diff.read(cx);
let buffer_id = diff.buffer_id;
- let buffers = self.buffers.borrow();
- let Some(buffer_state) = buffers.get(&buffer_id) else {
+ let Some(buffer_state) = self.buffers.get(&buffer_id) else {
return;
};
@@ -2471,7 +2440,7 @@ impl MultiBuffer {
let diff_change_range = range.to_offset(buffer);
let new_diff = diff.snapshot(cx);
- let mut snapshot = self.snapshot.borrow_mut();
+ let mut snapshot = self.snapshot.get_mut();
let base_text_changed = snapshot
.diffs
.get(&buffer_id)
@@ -2515,13 +2484,16 @@ impl MultiBuffer {
}
}
- self.sync_diff_transforms(
+ let edits = Self::sync_diff_transforms(
&mut snapshot,
excerpt_edits,
DiffChangeKind::DiffUpdated {
base_changed: base_text_changed,
},
);
+ if !edits.is_empty() {
+ self.subscriptions.publish(edits);
+ }
cx.emit(Event::Edited {
edited_buffer: None,
});
@@ -2529,19 +2501,17 @@ impl MultiBuffer {
pub fn all_buffers(&self) -> HashSet<Entity<Buffer>> {
self.buffers
- .borrow()
.values()
.map(|state| state.buffer.clone())
.collect()
}
pub fn all_buffer_ids(&self) -> Vec<BufferId> {
- self.buffers.borrow().keys().copied().collect()
+ self.buffers.keys().copied().collect()
}
pub fn buffer(&self, buffer_id: BufferId) -> Option<Entity<Buffer>> {
self.buffers
- .borrow()
.get(&buffer_id)
.map(|state| state.buffer.clone())
}
@@ -2583,10 +2553,7 @@ impl MultiBuffer {
}
pub fn for_each_buffer(&self, mut f: impl FnMut(&Entity<Buffer>)) {
- self.buffers
- .borrow()
- .values()
- .for_each(|state| f(&state.buffer))
+ self.buffers.values().for_each(|state| f(&state.buffer))
}
pub fn title<'a>(&'a self, cx: &'a App) -> Cow<'a, str> {
@@ -2655,7 +2622,7 @@ impl MultiBuffer {
/// Preserve preview tabs containing this multibuffer until additional edits occur.
pub fn refresh_preview(&self, cx: &mut Context<Self>) {
- for buffer_state in self.buffers.borrow().values() {
+ for buffer_state in self.buffers.values() {
buffer_state
.buffer
.update(cx, |buffer, _cx| buffer.refresh_preview());
@@ -2665,7 +2632,6 @@ impl MultiBuffer {
/// Whether we should preserve the preview status of a tab containing this multi-buffer.
pub fn preserve_preview(&self, cx: &App) -> bool {
self.buffers
- .borrow()
.values()
.all(|state| state.buffer.read(cx).preserve_preview())
}
@@ -2694,7 +2660,7 @@ impl MultiBuffer {
}
pub fn set_all_diff_hunks_expanded(&mut self, cx: &mut Context<Self>) {
- self.snapshot.borrow_mut().all_diff_hunks_expanded = true;
+ self.snapshot.get_mut().all_diff_hunks_expanded = true;
self.expand_or_collapse_diff_hunks(vec![Anchor::min()..Anchor::max()], true, cx);
}
@@ -2703,7 +2669,7 @@ impl MultiBuffer {
}
pub fn set_all_diff_hunks_collapsed(&mut self, cx: &mut Context<Self>) {
- self.snapshot.borrow_mut().all_diff_hunks_expanded = false;
+ self.snapshot.get_mut().all_diff_hunks_expanded = false;
self.expand_or_collapse_diff_hunks(vec![Anchor::min()..Anchor::max()], false, cx);
}
@@ -2764,7 +2730,7 @@ impl MultiBuffer {
return;
}
self.sync(cx);
- let mut snapshot = self.snapshot.borrow_mut();
+ let mut snapshot = self.snapshot.get_mut();
let mut excerpt_edits = Vec::new();
let mut last_hunk_row = None;
for (range, end_excerpt_id) in ranges {
@@ -2795,11 +2761,14 @@ impl MultiBuffer {
}
}
- self.sync_diff_transforms(
+ let edits = Self::sync_diff_transforms(
&mut snapshot,
excerpt_edits,
DiffChangeKind::ExpandOrCollapseHunks { expand },
);
+ if !edits.is_empty() {
+ self.subscriptions.publish(edits);
+ }
cx.emit(Event::DiffHunksToggled);
cx.emit(Event::Edited {
edited_buffer: None,
@@ -2833,7 +2802,7 @@ impl MultiBuffer {
) {
self.sync(cx);
- let mut snapshot = self.snapshot.borrow_mut();
+ let mut snapshot = self.snapshot.get_mut();
let locator = snapshot.excerpt_locator_for_id(id);
let mut new_excerpts = SumTree::default();
let mut cursor = snapshot
@@ -2883,7 +2852,10 @@ impl MultiBuffer {
drop(cursor);
snapshot.excerpts = new_excerpts;
- self.sync_diff_transforms(&mut snapshot, edits, DiffChangeKind::BufferEdited);
+ let edits = Self::sync_diff_transforms(&mut snapshot, edits, DiffChangeKind::BufferEdited);
+ if !edits.is_empty() {
+ self.subscriptions.publish(edits);
+ }
cx.emit(Event::Edited {
edited_buffer: None,
});
@@ -2906,7 +2878,7 @@ impl MultiBuffer {
self.expand_excerpts_with_paths(ids, line_count, direction, cx);
return;
}
- let mut snapshot = self.snapshot.borrow_mut();
+ let mut snapshot = self.snapshot.get_mut();
let ids = ids.into_iter().collect::<Vec<_>>();
let locators = snapshot.excerpt_locators_for_ids(ids.iter().copied());
@@ -2987,7 +2959,10 @@ impl MultiBuffer {
drop(cursor);
snapshot.excerpts = new_excerpts;
- self.sync_diff_transforms(&mut snapshot, edits, DiffChangeKind::BufferEdited);
+ let edits = Self::sync_diff_transforms(&mut snapshot, edits, DiffChangeKind::BufferEdited);
+ if !edits.is_empty() {
+ self.subscriptions.publish(edits);
+ }
cx.emit(Event::Edited {
edited_buffer: None,
});
@@ -3008,18 +2983,19 @@ impl MultiBuffer {
let mut has_deleted_file = false;
let mut has_conflict = false;
let mut edited = false;
- let mut buffers = self.buffers.borrow_mut();
- for buffer_state in buffers.values_mut() {
+ for buffer_state in self.buffers.values() {
let buffer = buffer_state.buffer.read(cx);
let version = buffer.version();
let non_text_state_update_count = buffer.non_text_state_update_count();
- let buffer_edited = version.changed_since(&buffer_state.last_version);
+ let buffer_edited = version.changed_since(&buffer_state.last_version.borrow());
let buffer_non_text_state_updated =
- non_text_state_update_count > buffer_state.last_non_text_state_update_count;
+ non_text_state_update_count > buffer_state.last_non_text_state_update_count.get();
if buffer_edited || buffer_non_text_state_updated {
- buffer_state.last_version = version;
- buffer_state.last_non_text_state_update_count = non_text_state_update_count;
+ *buffer_state.last_version.borrow_mut() = version;
+ buffer_state
+ .last_non_text_state_update_count
+ .set(non_text_state_update_count);
excerpts_to_edit.extend(
buffer_state
.excerpts
@@ -3110,17 +3086,19 @@ impl MultiBuffer {
drop(cursor);
snapshot.excerpts = new_excerpts;
- self.sync_diff_transforms(&mut snapshot, edits, DiffChangeKind::BufferEdited);
+ let edits = Self::sync_diff_transforms(&mut snapshot, edits, DiffChangeKind::BufferEdited);
+ if !edits.is_empty() {
+ self.subscriptions.publish(edits);
+ }
}
fn sync_diff_transforms(
- &self,
snapshot: &mut MultiBufferSnapshot,
excerpt_edits: Vec<text::Edit<ExcerptOffset>>,
change_kind: DiffChangeKind,
- ) {
+ ) -> Vec<Edit<usize>> {
if excerpt_edits.is_empty() {
- return;
+ return vec![];
}
let mut excerpts = snapshot.excerpts.cursor::<ExcerptOffset>(());