@@ -1,16 +1,13 @@
-use std::ops::Range;
+use std::{ops::Range, sync::Arc};
-use buffer_diff::{BufferDiff, BufferDiffSnapshot};
-use collections::HashMap;
use feature_flags::{FeatureFlag, FeatureFlagAppExt as _};
use gpui::{
Action, AppContext as _, Entity, EventEmitter, Focusable, NoAction, Subscription, WeakEntity,
};
-use language::{Buffer, BufferSnapshot, Capability};
-use multi_buffer::{Anchor, ExcerptRange, MultiBuffer, MultiBufferSnapshot, PathKey};
+use language::{Buffer, Capability, LanguageRegistry};
+use multi_buffer::{Anchor, ExcerptRange, MultiBuffer, PathKey};
use project::Project;
use rope::Point;
-use text::{BufferId, OffsetRangeExt as _};
use ui::{
App, Context, InteractiveElement as _, IntoElement as _, ParentElement as _, Render,
Styled as _, Window, div,
@@ -140,86 +137,18 @@ impl SplittableEditor {
return;
};
let project = workspace.read(cx).project().clone();
- let language_registry = project.read(cx).languages().clone();
-
- let primary_multibuffer = self.primary_editor.read(cx).buffer().read(cx);
-
- let base_text_buffers_by_main_buffer_id: HashMap<
- BufferId,
- (Entity<Buffer>, BufferDiffSnapshot),
- > = primary_multibuffer
- .all_buffer_ids_iter()
- .filter_map(|main_buffer_id| {
- let diff = primary_multibuffer.diff_for(main_buffer_id)?;
- let base_text_buffer = cx.new(|cx| {
- let base_text = diff.read(cx).base_text();
- let mut buffer = Buffer::local_normalized(
- base_text.as_rope().clone(),
- base_text.line_ending(),
- cx,
- );
- buffer.set_language(base_text.language().cloned(), cx);
- buffer.set_language_registry(language_registry.clone());
- buffer
- });
- Some((
- main_buffer_id,
- (base_text_buffer, diff.read(cx).snapshot(cx)),
- ))
- })
- .collect();
- let snapshot = primary_multibuffer.snapshot(cx);
- let mut excerpt_ranges_by_base_buffer: HashMap<
- Entity<Buffer>,
- (PathKey, Vec<ExcerptRange<Point>>),
- > = HashMap::default();
- for (path_key, excerpt_id) in primary_multibuffer.excerpts_with_paths() {
- let main_buffer = snapshot.buffer_for_excerpt(*excerpt_id).unwrap();
- let excerpt_range = snapshot.excerpt_range_for_excerpt(*excerpt_id).unwrap();
- let (base_text_buffer, diff) = base_text_buffers_by_main_buffer_id
- .get(&main_buffer.remote_id())
- .unwrap();
- let point_to_base_text_point = |point: Point| {
- let row = diff.row_to_base_text_row(point.row, &main_buffer);
- let column = diff.base_text().line_len(row);
- Point::new(row, column)
- };
- let primary = excerpt_range.primary.to_point(&main_buffer);
- let context = excerpt_range.context.to_point(&main_buffer);
- let translated_range = ExcerptRange {
- primary: point_to_base_text_point(primary.start)
- ..point_to_base_text_point(primary.end),
- context: point_to_base_text_point(context.start)
- ..point_to_base_text_point(context.end),
- };
- excerpt_ranges_by_base_buffer
- .entry(base_text_buffer.clone())
- .or_insert((path_key.clone(), Vec::new()))
- .1
- .push(translated_range);
- }
-
- let secondary_multibuffer = cx.new(|cx| {
- let mut multibuffer = MultiBuffer::new(Capability::ReadOnly);
- for (base_text_buffer, (path_key, ranges)) in excerpt_ranges_by_base_buffer {
- let base_text_buffer_snapshot = base_text_buffer.read(cx).snapshot();
- multibuffer.update_path_excerpts(
- path_key,
- base_text_buffer,
- &base_text_buffer_snapshot,
- ranges,
- cx,
- );
- }
- multibuffer
- });
- let secondary_editor =
- cx.new(|cx| Editor::for_multibuffer(secondary_multibuffer, Some(project), window, cx));
// FIXME
// - have to subscribe to the diffs to update the base text buffers (and handle language changed I think?)
- // - implement SplittableEditor::set_excerpts_for_path
+ let secondary_editor = cx.new(|cx| {
+ let multibuffer = cx.new(|cx| {
+ let mut multibuffer = MultiBuffer::new(Capability::ReadOnly);
+ multibuffer.set_all_diff_hunks_expanded(cx);
+ multibuffer
+ });
+ Editor::for_multibuffer(multibuffer, Some(project.clone()), window, cx)
+ });
let secondary_pane = cx.new(|cx| {
let mut pane = Pane::new(
workspace.downgrade(),
@@ -260,15 +189,20 @@ impl SplittableEditor {
has_latest_selection: false,
_subscriptions: subscriptions,
};
- for (path_key, diff, original_range, original_buffer) in whatever {
- secondary.sync_path_excerpts_for_buffer(
- path_key,
- diff,
- original_range,
- original_buffer,
- cx,
- );
- }
+ self.primary_editor.update(cx, |editor, cx| {
+ editor.buffer().update(cx, |primary_multibuffer, cx| {
+ primary_multibuffer.set_show_deleted_hunks(false, cx);
+ let paths = primary_multibuffer.paths().collect::<Vec<_>>();
+ for path in paths {
+ secondary.sync_path_excerpts(
+ path,
+ primary_multibuffer,
+ project.read(cx).languages().clone(),
+ cx,
+ );
+ }
+ })
+ });
self.secondary = Some(secondary);
let primary_pane = self.panes.first_pane();
@@ -284,8 +218,8 @@ impl SplittableEditor {
};
self.panes.remove(&secondary.pane).unwrap();
self.primary_editor.update(cx, |primary, cx| {
- primary.buffer().update(cx, |buffer, _| {
- buffer.set_filter_mode(None);
+ primary.buffer().update(cx, |buffer, cx| {
+ buffer.set_show_deleted_hunks(true, cx);
});
});
cx.notify();
@@ -316,17 +250,28 @@ impl SplittableEditor {
context_line_count: u32,
cx: &mut Context<Self>,
) -> (Vec<Range<Anchor>>, bool) {
- let (anchors, added_a_new_excerpt) =
- self.primary_editor
- .read(cx)
- .buffer()
- .update(cx, |multibuffer, cx| {
- multibuffer.set_excerpts_for_path(path, buffer, ranges, context_line_count, cx)
- });
- if let Some(secondary) = &mut self.secondary {
- secondary.sync_path_excerpts_for_buffer(cx);
- }
- (anchors, added_a_new_excerpt)
+ self.primary_editor.update(cx, |editor, cx| {
+ editor.buffer().update(cx, |primary_multibuffer, cx| {
+ let (anchors, added_a_new_excerpt) = primary_multibuffer.set_excerpts_for_path(
+ path.clone(),
+ buffer,
+ ranges,
+ context_line_count,
+ cx,
+ );
+ if let Some(secondary) = &mut self.secondary
+ && let Some(languages) = self
+ .workspace
+ .update(cx, |workspace, cx| {
+ workspace.project().read(cx).languages().clone()
+ })
+ .ok()
+ {
+ secondary.sync_path_excerpts(path, primary_multibuffer, languages, cx);
+ }
+ (anchors, added_a_new_excerpt)
+ })
+ })
}
}
@@ -367,35 +312,62 @@ impl Render for SplittableEditor {
}
impl SecondaryEditor {
- fn sync_path_excerpts_for_buffer(
+ fn sync_path_excerpts(
&mut self,
path_key: PathKey,
- main_buffer: &BufferSnapshot,
- primary_multibuffer: &MultiBuffer,
+ primary_multibuffer: &mut MultiBuffer,
+ languages: Arc<LanguageRegistry>,
cx: &mut App,
) {
+ let excerpt_id = primary_multibuffer
+ .excerpts_for_path(&path_key)
+ .next()
+ .unwrap();
+ let primary_multibuffer_snapshot = primary_multibuffer.snapshot(cx);
+ let main_buffer = primary_multibuffer_snapshot
+ .buffer_for_excerpt(excerpt_id)
+ .unwrap();
let diff = primary_multibuffer
.diff_for(main_buffer.remote_id())
.unwrap();
let diff = diff.read(cx).snapshot(cx);
- // option 1: hold onto the base text buffers in splittable editor so that we can check whether they exist yet
- // option 2: have the multibuffer continue to be fully responsible for holding the base text buffers; then need to be able to get a buffer out of the multibuffer based on a pathkey
- let base_text_buffer = self.editor.update(cx, |editor, cx| {
- editor
- .buffer()
- .update(cx, |buffer, cx| buffer.buffer_for_path_key)
- });
+ let base_text_buffer = self
+ .editor
+ .update(cx, |editor, cx| {
+ editor.buffer().update(cx, |secondary_multibuffer, cx| {
+ let excerpt_id = secondary_multibuffer.excerpts_for_path(&path_key).next()?;
+ let secondary_buffer_snapshot = secondary_multibuffer.snapshot(cx);
+ let buffer = secondary_buffer_snapshot
+ .buffer_for_excerpt(excerpt_id)
+ .unwrap();
+ Some(secondary_multibuffer.buffer(buffer.remote_id()).unwrap())
+ })
+ })
+ .unwrap_or_else(|| {
+ cx.new(|cx| {
+ let base_text = diff.base_text();
+ let mut buffer = Buffer::local_normalized(
+ base_text.as_rope().clone(),
+ base_text.line_ending(),
+ cx,
+ );
+ buffer.set_language(base_text.language().cloned(), cx);
+ buffer.set_language_registry(languages);
+ buffer
+ })
+ });
+ let base_text_buffer_snapshot = base_text_buffer.read(cx).snapshot();
let new = primary_multibuffer
.excerpts_for_buffer(main_buffer.remote_id(), cx)
.into_iter()
- .map(|(excerpt_id, excerpt_range)| {
+ .map(|(_, excerpt_range)| {
let point_to_base_text_point = |point: Point| {
- let row = diff.row_to_base_text_row(point.row, &main_buffer);
+ let row = diff.row_to_base_text_row(point.row, main_buffer);
let column = diff.base_text().line_len(row);
Point::new(row, column)
};
- let primary = excerpt_range.primary.to_point(&main_buffer);
- let context = excerpt_range.context.to_point(&main_buffer);
+ let primary = excerpt_range.primary.to_point(main_buffer);
+ let context = excerpt_range.context.to_point(main_buffer);
ExcerptRange {
primary: point_to_base_text_point(primary.start)
..point_to_base_text_point(primary.end),
@@ -410,7 +382,7 @@ impl SecondaryEditor {
buffer.update_path_excerpts(
path_key,
base_text_buffer,
- base_text_buffer_snapshot,
+ &base_text_buffer_snapshot,
new,
cx,
)
@@ -610,6 +610,7 @@ pub struct MultiBufferSnapshot {
replaced_excerpts: TreeMap<ExcerptId, ExcerptId>,
trailing_excerpt_update_count: usize,
all_diff_hunks_expanded: bool,
+ show_deleted_hunks: bool,
show_headers: bool,
}
@@ -1089,6 +1090,7 @@ impl MultiBuffer {
capability,
MultiBufferSnapshot {
show_headers: true,
+ show_deleted_hunks: true,
..MultiBufferSnapshot::default()
},
)
@@ -1862,6 +1864,7 @@ impl MultiBuffer {
replaced_excerpts,
trailing_excerpt_update_count,
all_diff_hunks_expanded: _,
+ show_deleted_hunks: _,
show_headers: _,
} = self.snapshot.get_mut();
let start = ExcerptDimension(MultiBufferOffset::ZERO);
@@ -2652,6 +2655,11 @@ impl MultiBuffer {
self.expand_or_collapse_diff_hunks(vec![Anchor::min()..Anchor::max()], false, cx);
}
+ pub fn set_show_deleted_hunks(&mut self, show: bool, cx: &mut Context<Self>) {
+ self.snapshot.get_mut().show_deleted_hunks = show;
+ self.expand_or_collapse_diff_hunks(vec![Anchor::min()..Anchor::max()], true, cx);
+ }
+
pub fn has_multiple_hunks(&self, cx: &App) -> bool {
self.read(cx)
.diff_hunks_in_range(Anchor::min()..Anchor::max())
@@ -2989,6 +2997,7 @@ impl MultiBuffer {
replaced_excerpts: _,
trailing_excerpt_update_count: _,
all_diff_hunks_expanded: _,
+ show_deleted_hunks: _,
show_headers: _,
} = snapshot;
*is_dirty = false;
@@ -3382,10 +3391,10 @@ impl MultiBuffer {
excerpt.id
);
- // FIXME don't push the deleted region if this is the RHS of a split
if !hunk.diff_base_byte_range.is_empty()
&& hunk_buffer_range.start >= edit_buffer_start
&& hunk_buffer_range.start <= excerpt_buffer_end
+ && snapshot.show_deleted_hunks
{
let base_text = diff.base_text();
let mut text_cursor =