In proposed change editors, apply diff hunks in batches (#18841)
Release Notes: - N/A
This commit is contained in:
parent
ff7aa024ee
commit
4139e2de23
4 changed files with 50 additions and 22 deletions
|
@ -6213,14 +6213,22 @@ impl Editor {
|
||||||
fn apply_selected_diff_hunks(&mut self, _: &ApplyDiffHunk, cx: &mut ViewContext<Self>) {
|
fn apply_selected_diff_hunks(&mut self, _: &ApplyDiffHunk, cx: &mut ViewContext<Self>) {
|
||||||
let snapshot = self.buffer.read(cx).snapshot(cx);
|
let snapshot = self.buffer.read(cx).snapshot(cx);
|
||||||
let hunks = hunks_for_selections(&snapshot, &self.selections.disjoint_anchors());
|
let hunks = hunks_for_selections(&snapshot, &self.selections.disjoint_anchors());
|
||||||
|
let mut ranges_by_buffer = HashMap::default();
|
||||||
self.transact(cx, |editor, cx| {
|
self.transact(cx, |editor, cx| {
|
||||||
for hunk in hunks {
|
for hunk in hunks {
|
||||||
if let Some(buffer) = editor.buffer.read(cx).buffer(hunk.buffer_id) {
|
if let Some(buffer) = editor.buffer.read(cx).buffer(hunk.buffer_id) {
|
||||||
buffer.update(cx, |buffer, cx| {
|
ranges_by_buffer
|
||||||
buffer.merge_into_base(Some(hunk.buffer_range.to_offset(buffer)), cx);
|
.entry(buffer.clone())
|
||||||
});
|
.or_insert_with(Vec::new)
|
||||||
|
.push(hunk.buffer_range.to_offset(buffer.read(cx)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (buffer, ranges) in ranges_by_buffer {
|
||||||
|
buffer.update(cx, |buffer, cx| {
|
||||||
|
buffer.merge_into_base(ranges, cx);
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -350,7 +350,7 @@ impl Editor {
|
||||||
.next()?;
|
.next()?;
|
||||||
|
|
||||||
buffer.update(cx, |branch_buffer, cx| {
|
buffer.update(cx, |branch_buffer, cx| {
|
||||||
branch_buffer.merge_into_base(Some(range), cx);
|
branch_buffer.merge_into_base(vec![range], cx);
|
||||||
});
|
});
|
||||||
|
|
||||||
None
|
None
|
||||||
|
@ -360,7 +360,7 @@ impl Editor {
|
||||||
let buffers = self.buffer.read(cx).all_buffers();
|
let buffers = self.buffer.read(cx).all_buffers();
|
||||||
for branch_buffer in buffers {
|
for branch_buffer in buffers {
|
||||||
branch_buffer.update(cx, |branch_buffer, cx| {
|
branch_buffer.update(cx, |branch_buffer, cx| {
|
||||||
branch_buffer.merge_into_base(None, cx);
|
branch_buffer.merge_into_base(Vec::new(), cx);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -827,26 +827,46 @@ impl Buffer {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Applies all of the changes in this buffer that intersect the given `range`
|
/// Applies all of the changes in this buffer that intersect any of the
|
||||||
/// to its base buffer. This buffer must be a branch buffer to call this method.
|
/// given `ranges` to its base buffer.
|
||||||
pub fn merge_into_base(&mut self, range: Option<Range<usize>>, cx: &mut ModelContext<Self>) {
|
///
|
||||||
|
/// If `ranges` is empty, then all changes will be applied. This buffer must
|
||||||
|
/// be a branch buffer to call this method.
|
||||||
|
pub fn merge_into_base(&mut self, ranges: Vec<Range<usize>>, cx: &mut ModelContext<Self>) {
|
||||||
let Some(base_buffer) = self.diff_base_buffer() else {
|
let Some(base_buffer) = self.diff_base_buffer() else {
|
||||||
debug_panic!("not a branch buffer");
|
debug_panic!("not a branch buffer");
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let mut ranges = if ranges.is_empty() {
|
||||||
|
&[0..usize::MAX]
|
||||||
|
} else {
|
||||||
|
ranges.as_slice()
|
||||||
|
}
|
||||||
|
.into_iter()
|
||||||
|
.peekable();
|
||||||
|
|
||||||
let mut edits = Vec::new();
|
let mut edits = Vec::new();
|
||||||
for edit in self.edits_since::<usize>(&base_buffer.read(cx).version()) {
|
for edit in self.edits_since::<usize>(&base_buffer.read(cx).version()) {
|
||||||
if let Some(range) = &range {
|
let mut is_included = false;
|
||||||
if range.start > edit.new.end || edit.new.start > range.end {
|
while let Some(range) = ranges.peek() {
|
||||||
continue;
|
if range.end < edit.new.start {
|
||||||
|
ranges.next().unwrap();
|
||||||
|
} else {
|
||||||
|
if range.start <= edit.new.end {
|
||||||
|
is_included = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if is_included {
|
||||||
edits.push((
|
edits.push((
|
||||||
edit.old.clone(),
|
edit.old.clone(),
|
||||||
self.text_for_range(edit.new.clone()).collect::<String>(),
|
self.text_for_range(edit.new.clone()).collect::<String>(),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let operation = base_buffer.update(cx, |base_buffer, cx| {
|
let operation = base_buffer.update(cx, |base_buffer, cx| {
|
||||||
cx.emit(BufferEvent::DiffBaseChanged);
|
cx.emit(BufferEvent::DiffBaseChanged);
|
||||||
|
|
|
@ -2472,7 +2472,7 @@ fn test_branch_and_merge(cx: &mut TestAppContext) {
|
||||||
|
|
||||||
// Merging the branch applies all of its changes to the base.
|
// Merging the branch applies all of its changes to the base.
|
||||||
branch_buffer.update(cx, |branch_buffer, cx| {
|
branch_buffer.update(cx, |branch_buffer, cx| {
|
||||||
branch_buffer.merge_into_base(None, cx);
|
branch_buffer.merge_into_base(Vec::new(), cx);
|
||||||
});
|
});
|
||||||
|
|
||||||
branch_buffer.update(cx, |branch_buffer, cx| {
|
branch_buffer.update(cx, |branch_buffer, cx| {
|
||||||
|
@ -2494,7 +2494,7 @@ fn test_merge_into_base(cx: &mut TestAppContext) {
|
||||||
// Make 3 edits, merge one into the base.
|
// Make 3 edits, merge one into the base.
|
||||||
branch.update(cx, |branch, cx| {
|
branch.update(cx, |branch, cx| {
|
||||||
branch.edit([(0..3, "ABC"), (7..9, "HI"), (11..11, "LMN")], None, cx);
|
branch.edit([(0..3, "ABC"), (7..9, "HI"), (11..11, "LMN")], None, cx);
|
||||||
branch.merge_into_base(Some(5..8), cx);
|
branch.merge_into_base(vec![5..8], cx);
|
||||||
});
|
});
|
||||||
|
|
||||||
branch.read_with(cx, |branch, _| assert_eq!(branch.text(), "ABCdefgHIjkLMN"));
|
branch.read_with(cx, |branch, _| assert_eq!(branch.text(), "ABCdefgHIjkLMN"));
|
||||||
|
@ -2503,13 +2503,13 @@ fn test_merge_into_base(cx: &mut TestAppContext) {
|
||||||
// Undo the one already-merged edit. Merge that into the base.
|
// Undo the one already-merged edit. Merge that into the base.
|
||||||
branch.update(cx, |branch, cx| {
|
branch.update(cx, |branch, cx| {
|
||||||
branch.edit([(7..9, "hi")], None, cx);
|
branch.edit([(7..9, "hi")], None, cx);
|
||||||
branch.merge_into_base(Some(5..8), cx);
|
branch.merge_into_base(vec![5..8], cx);
|
||||||
});
|
});
|
||||||
base.read_with(cx, |base, _| assert_eq!(base.text(), "abcdefghijk"));
|
base.read_with(cx, |base, _| assert_eq!(base.text(), "abcdefghijk"));
|
||||||
|
|
||||||
// Merge an insertion into the base.
|
// Merge an insertion into the base.
|
||||||
branch.update(cx, |branch, cx| {
|
branch.update(cx, |branch, cx| {
|
||||||
branch.merge_into_base(Some(11..11), cx);
|
branch.merge_into_base(vec![11..11], cx);
|
||||||
});
|
});
|
||||||
|
|
||||||
branch.read_with(cx, |branch, _| assert_eq!(branch.text(), "ABCdefghijkLMN"));
|
branch.read_with(cx, |branch, _| assert_eq!(branch.text(), "ABCdefghijkLMN"));
|
||||||
|
@ -2518,7 +2518,7 @@ fn test_merge_into_base(cx: &mut TestAppContext) {
|
||||||
// Deleted the inserted text and merge that into the base.
|
// Deleted the inserted text and merge that into the base.
|
||||||
branch.update(cx, |branch, cx| {
|
branch.update(cx, |branch, cx| {
|
||||||
branch.edit([(11..14, "")], None, cx);
|
branch.edit([(11..14, "")], None, cx);
|
||||||
branch.merge_into_base(Some(10..11), cx);
|
branch.merge_into_base(vec![10..11], cx);
|
||||||
});
|
});
|
||||||
|
|
||||||
base.read_with(cx, |base, _| assert_eq!(base.text(), "abcdefghijk"));
|
base.read_with(cx, |base, _| assert_eq!(base.text(), "abcdefghijk"));
|
||||||
|
@ -2534,7 +2534,7 @@ fn test_undo_after_merge_into_base(cx: &mut TestAppContext) {
|
||||||
// Make 2 edits, merge one into the base.
|
// Make 2 edits, merge one into the base.
|
||||||
branch.update(cx, |branch, cx| {
|
branch.update(cx, |branch, cx| {
|
||||||
branch.edit([(0..3, "ABC"), (7..9, "HI")], None, cx);
|
branch.edit([(0..3, "ABC"), (7..9, "HI")], None, cx);
|
||||||
branch.merge_into_base(Some(7..7), cx);
|
branch.merge_into_base(vec![7..7], cx);
|
||||||
});
|
});
|
||||||
base.read_with(cx, |base, _| assert_eq!(base.text(), "abcdefgHIjk"));
|
base.read_with(cx, |base, _| assert_eq!(base.text(), "abcdefgHIjk"));
|
||||||
branch.read_with(cx, |branch, _| assert_eq!(branch.text(), "ABCdefgHIjk"));
|
branch.read_with(cx, |branch, _| assert_eq!(branch.text(), "ABCdefgHIjk"));
|
||||||
|
@ -2548,7 +2548,7 @@ fn test_undo_after_merge_into_base(cx: &mut TestAppContext) {
|
||||||
|
|
||||||
// Merge that operation into the base again.
|
// Merge that operation into the base again.
|
||||||
branch.update(cx, |branch, cx| {
|
branch.update(cx, |branch, cx| {
|
||||||
branch.merge_into_base(Some(7..7), cx);
|
branch.merge_into_base(vec![7..7], cx);
|
||||||
});
|
});
|
||||||
base.read_with(cx, |base, _| assert_eq!(base.text(), "abcdefgHIjk"));
|
base.read_with(cx, |base, _| assert_eq!(base.text(), "abcdefgHIjk"));
|
||||||
branch.read_with(cx, |branch, _| assert_eq!(branch.text(), "ABCdefgHIjk"));
|
branch.read_with(cx, |branch, _| assert_eq!(branch.text(), "ABCdefgHIjk"));
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue