Building, but failing test WIP
This commit is contained in:
parent
065734e1de
commit
04fc1d5982
14 changed files with 492 additions and 419 deletions
|
@ -20,15 +20,15 @@ fn init_logger() {
|
|||
fn test_edit() {
|
||||
let mut buffer = Buffer::new(0, 0, History::new("abc".into()));
|
||||
assert_eq!(buffer.text(), "abc");
|
||||
buffer.edit(vec![3..3], "def");
|
||||
buffer.edit(3..3, "def");
|
||||
assert_eq!(buffer.text(), "abcdef");
|
||||
buffer.edit(vec![0..0], "ghi");
|
||||
buffer.edit(0..0, "ghi");
|
||||
assert_eq!(buffer.text(), "ghiabcdef");
|
||||
buffer.edit(vec![5..5], "jkl");
|
||||
buffer.edit(5..5, "jkl");
|
||||
assert_eq!(buffer.text(), "ghiabjklcdef");
|
||||
buffer.edit(vec![6..7], "");
|
||||
buffer.edit(6..7, "");
|
||||
assert_eq!(buffer.text(), "ghiabjlcdef");
|
||||
buffer.edit(vec![4..9], "mno");
|
||||
buffer.edit(4..9, "mno");
|
||||
assert_eq!(buffer.text(), "ghiamnoef");
|
||||
}
|
||||
|
||||
|
@ -52,8 +52,8 @@ fn test_random_edits(mut rng: StdRng) {
|
|||
);
|
||||
|
||||
for _i in 0..operations {
|
||||
let (old_ranges, new_text, _) = buffer.randomly_edit(&mut rng, 5);
|
||||
for old_range in old_ranges.iter().rev() {
|
||||
let (edits, _) = buffer.randomly_edit(&mut rng, 5);
|
||||
for (old_range, new_text) in edits.iter().rev() {
|
||||
reference_string.replace_range(old_range.clone(), &new_text);
|
||||
}
|
||||
assert_eq!(buffer.text(), reference_string);
|
||||
|
@ -151,10 +151,10 @@ fn test_random_edits(mut rng: StdRng) {
|
|||
#[test]
|
||||
fn test_line_len() {
|
||||
let mut buffer = Buffer::new(0, 0, History::new("".into()));
|
||||
buffer.edit(vec![0..0], "abcd\nefg\nhij");
|
||||
buffer.edit(vec![12..12], "kl\nmno");
|
||||
buffer.edit(vec![18..18], "\npqrs\n");
|
||||
buffer.edit(vec![18..21], "\nPQ");
|
||||
buffer.edit(0..0, "abcd\nefg\nhij");
|
||||
buffer.edit(12..12, "kl\nmno");
|
||||
buffer.edit(18..18, "\npqrs\n");
|
||||
buffer.edit(18..21, "\nPQ");
|
||||
|
||||
assert_eq!(buffer.line_len(0), 4);
|
||||
assert_eq!(buffer.line_len(1), 3);
|
||||
|
@ -281,10 +281,10 @@ fn test_text_summary_for_range() {
|
|||
#[test]
|
||||
fn test_chars_at() {
|
||||
let mut buffer = Buffer::new(0, 0, History::new("".into()));
|
||||
buffer.edit(vec![0..0], "abcd\nefgh\nij");
|
||||
buffer.edit(vec![12..12], "kl\nmno");
|
||||
buffer.edit(vec![18..18], "\npqrs");
|
||||
buffer.edit(vec![18..21], "\nPQ");
|
||||
buffer.edit(0..0, "abcd\nefgh\nij");
|
||||
buffer.edit(12..12, "kl\nmno");
|
||||
buffer.edit(18..18, "\npqrs");
|
||||
buffer.edit(18..21, "\nPQ");
|
||||
|
||||
let chars = buffer.chars_at(Point::new(0, 0));
|
||||
assert_eq!(chars.collect::<String>(), "abcd\nefgh\nijkl\nmno\nPQrs");
|
||||
|
@ -303,8 +303,8 @@ fn test_chars_at() {
|
|||
|
||||
// Regression test:
|
||||
let mut buffer = Buffer::new(0, 0, History::new("".into()));
|
||||
buffer.edit(vec![0..0], "[workspace]\nmembers = [\n \"xray_core\",\n \"xray_server\",\n \"xray_cli\",\n \"xray_wasm\",\n]\n");
|
||||
buffer.edit(vec![60..60], "\n");
|
||||
buffer.edit(0..0, "[workspace]\nmembers = [\n \"xray_core\",\n \"xray_server\",\n \"xray_cli\",\n \"xray_wasm\",\n]\n");
|
||||
buffer.edit(60..60, "\n");
|
||||
|
||||
let chars = buffer.chars_at(Point::new(6, 0));
|
||||
assert_eq!(chars.collect::<String>(), " \"xray_wasm\",\n]\n");
|
||||
|
@ -313,32 +313,32 @@ fn test_chars_at() {
|
|||
#[test]
|
||||
fn test_anchors() {
|
||||
let mut buffer = Buffer::new(0, 0, History::new("".into()));
|
||||
buffer.edit(vec![0..0], "abc");
|
||||
buffer.edit(0..0, "abc");
|
||||
let left_anchor = buffer.anchor_before(2);
|
||||
let right_anchor = buffer.anchor_after(2);
|
||||
|
||||
buffer.edit(vec![1..1], "def\n");
|
||||
buffer.edit(1..1, "def\n");
|
||||
assert_eq!(buffer.text(), "adef\nbc");
|
||||
assert_eq!(left_anchor.to_offset(&buffer), 6);
|
||||
assert_eq!(right_anchor.to_offset(&buffer), 6);
|
||||
assert_eq!(left_anchor.to_point(&buffer), Point { row: 1, column: 1 });
|
||||
assert_eq!(right_anchor.to_point(&buffer), Point { row: 1, column: 1 });
|
||||
|
||||
buffer.edit(vec![2..3], "");
|
||||
buffer.edit(2..3, "");
|
||||
assert_eq!(buffer.text(), "adf\nbc");
|
||||
assert_eq!(left_anchor.to_offset(&buffer), 5);
|
||||
assert_eq!(right_anchor.to_offset(&buffer), 5);
|
||||
assert_eq!(left_anchor.to_point(&buffer), Point { row: 1, column: 1 });
|
||||
assert_eq!(right_anchor.to_point(&buffer), Point { row: 1, column: 1 });
|
||||
|
||||
buffer.edit(vec![5..5], "ghi\n");
|
||||
buffer.edit(5..5, "ghi\n");
|
||||
assert_eq!(buffer.text(), "adf\nbghi\nc");
|
||||
assert_eq!(left_anchor.to_offset(&buffer), 5);
|
||||
assert_eq!(right_anchor.to_offset(&buffer), 9);
|
||||
assert_eq!(left_anchor.to_point(&buffer), Point { row: 1, column: 1 });
|
||||
assert_eq!(right_anchor.to_point(&buffer), Point { row: 2, column: 0 });
|
||||
|
||||
buffer.edit(vec![7..9], "");
|
||||
buffer.edit(7..9, "");
|
||||
assert_eq!(buffer.text(), "adf\nbghc");
|
||||
assert_eq!(left_anchor.to_offset(&buffer), 5);
|
||||
assert_eq!(right_anchor.to_offset(&buffer), 7);
|
||||
|
@ -434,7 +434,7 @@ fn test_anchors_at_start_and_end() {
|
|||
let before_start_anchor = buffer.anchor_before(0);
|
||||
let after_end_anchor = buffer.anchor_after(0);
|
||||
|
||||
buffer.edit(vec![0..0], "abc");
|
||||
buffer.edit(0..0, "abc");
|
||||
assert_eq!(buffer.text(), "abc");
|
||||
assert_eq!(before_start_anchor.to_offset(&buffer), 0);
|
||||
assert_eq!(after_end_anchor.to_offset(&buffer), 3);
|
||||
|
@ -442,8 +442,8 @@ fn test_anchors_at_start_and_end() {
|
|||
let after_start_anchor = buffer.anchor_after(0);
|
||||
let before_end_anchor = buffer.anchor_before(3);
|
||||
|
||||
buffer.edit(vec![3..3], "def");
|
||||
buffer.edit(vec![0..0], "ghi");
|
||||
buffer.edit(3..3, "def");
|
||||
buffer.edit(0..0, "ghi");
|
||||
assert_eq!(buffer.text(), "ghiabcdef");
|
||||
assert_eq!(before_start_anchor.to_offset(&buffer), 0);
|
||||
assert_eq!(after_start_anchor.to_offset(&buffer), 3);
|
||||
|
@ -457,9 +457,9 @@ fn test_undo_redo() {
|
|||
// Set group interval to zero so as to not group edits in the undo stack.
|
||||
buffer.history.group_interval = Duration::from_secs(0);
|
||||
|
||||
buffer.edit(vec![1..1], "abx");
|
||||
buffer.edit(vec![3..4], "yzef");
|
||||
buffer.edit(vec![3..5], "cd");
|
||||
buffer.edit(1..1, "abx");
|
||||
buffer.edit(3..4, "yzef");
|
||||
buffer.edit(3..5, "cd");
|
||||
assert_eq!(buffer.text(), "1abcdef234");
|
||||
|
||||
let entries = buffer.history.undo_stack.clone();
|
||||
|
@ -493,19 +493,19 @@ fn test_history() {
|
|||
let mut buffer = Buffer::new(0, 0, History::new("123456".into()));
|
||||
|
||||
buffer.start_transaction_at(now);
|
||||
buffer.edit(vec![2..4], "cd");
|
||||
buffer.edit(2..4, "cd");
|
||||
buffer.end_transaction_at(now);
|
||||
assert_eq!(buffer.text(), "12cd56");
|
||||
|
||||
buffer.start_transaction_at(now);
|
||||
buffer.edit(vec![4..5], "e");
|
||||
buffer.edit(4..5, "e");
|
||||
buffer.end_transaction_at(now).unwrap();
|
||||
assert_eq!(buffer.text(), "12cde6");
|
||||
|
||||
now += buffer.history.group_interval + Duration::from_millis(1);
|
||||
buffer.start_transaction_at(now);
|
||||
buffer.edit(vec![0..1], "a");
|
||||
buffer.edit(vec![1..1], "b");
|
||||
buffer.edit(0..1, "a");
|
||||
buffer.edit(1..1, "b");
|
||||
buffer.end_transaction_at(now).unwrap();
|
||||
assert_eq!(buffer.text(), "ab2cde6");
|
||||
|
||||
|
@ -537,19 +537,19 @@ fn test_finalize_last_transaction() {
|
|||
let mut buffer = Buffer::new(0, 0, History::new("123456".into()));
|
||||
|
||||
buffer.start_transaction_at(now);
|
||||
buffer.edit(vec![2..4], "cd");
|
||||
buffer.edit(2..4, "cd");
|
||||
buffer.end_transaction_at(now);
|
||||
assert_eq!(buffer.text(), "12cd56");
|
||||
|
||||
buffer.finalize_last_transaction();
|
||||
buffer.start_transaction_at(now);
|
||||
buffer.edit(vec![4..5], "e");
|
||||
buffer.edit(4..5, "e");
|
||||
buffer.end_transaction_at(now).unwrap();
|
||||
assert_eq!(buffer.text(), "12cde6");
|
||||
|
||||
buffer.start_transaction_at(now);
|
||||
buffer.edit(vec![0..1], "a");
|
||||
buffer.edit(vec![1..1], "b");
|
||||
buffer.edit(0..1, "a");
|
||||
buffer.edit(1..1, "b");
|
||||
buffer.end_transaction_at(now).unwrap();
|
||||
assert_eq!(buffer.text(), "ab2cde6");
|
||||
|
||||
|
@ -572,8 +572,8 @@ fn test_edited_ranges_for_transaction() {
|
|||
let mut buffer = Buffer::new(0, 0, History::new("1234567".into()));
|
||||
|
||||
buffer.start_transaction_at(now);
|
||||
buffer.edit(vec![2..4], "cd");
|
||||
buffer.edit(vec![6..6], "efg");
|
||||
buffer.edit(2..4, "cd");
|
||||
buffer.edit(6..6, "efg");
|
||||
buffer.end_transaction_at(now);
|
||||
assert_eq!(buffer.text(), "12cd56efg7");
|
||||
|
||||
|
@ -585,7 +585,7 @@ fn test_edited_ranges_for_transaction() {
|
|||
[2..4, 6..9]
|
||||
);
|
||||
|
||||
buffer.edit(vec![5..5], "hijk");
|
||||
buffer.edit(5..5, "hijk");
|
||||
assert_eq!(buffer.text(), "12cd5hijk6efg7");
|
||||
assert_eq!(
|
||||
buffer
|
||||
|
@ -594,7 +594,7 @@ fn test_edited_ranges_for_transaction() {
|
|||
[2..4, 10..13]
|
||||
);
|
||||
|
||||
buffer.edit(vec![4..4], "l");
|
||||
buffer.edit(4..4, "l");
|
||||
assert_eq!(buffer.text(), "12cdl5hijk6efg7");
|
||||
assert_eq!(
|
||||
buffer
|
||||
|
@ -612,11 +612,11 @@ fn test_concurrent_edits() {
|
|||
let mut buffer2 = Buffer::new(2, 0, History::new(text.into()));
|
||||
let mut buffer3 = Buffer::new(3, 0, History::new(text.into()));
|
||||
|
||||
let buf1_op = buffer1.edit(vec![1..2], "12");
|
||||
let buf1_op = buffer1.edit(1..2, "12");
|
||||
assert_eq!(buffer1.text(), "a12cdef");
|
||||
let buf2_op = buffer2.edit(vec![3..4], "34");
|
||||
let buf2_op = buffer2.edit(3..4, "34");
|
||||
assert_eq!(buffer2.text(), "abc34ef");
|
||||
let buf3_op = buffer3.edit(vec![5..6], "56");
|
||||
let buf3_op = buffer3.edit(5..6, "56");
|
||||
assert_eq!(buffer3.text(), "abcde56");
|
||||
|
||||
buffer1.apply_op(buf2_op.clone()).unwrap();
|
||||
|
@ -665,7 +665,7 @@ fn test_random_concurrent_edits(mut rng: StdRng) {
|
|||
let buffer = &mut buffers[replica_index];
|
||||
match rng.gen_range(0..=100) {
|
||||
0..=50 if mutation_count != 0 => {
|
||||
let op = buffer.randomly_edit(&mut rng, 5).2;
|
||||
let op = buffer.randomly_edit(&mut rng, 5).1;
|
||||
network.broadcast(buffer.replica_id, vec![op]);
|
||||
log::info!("buffer {} text: {:?}", buffer.replica_id, buffer.text());
|
||||
mutation_count -= 1;
|
||||
|
|
|
@ -91,26 +91,34 @@ impl HistoryEntry {
|
|||
self.transaction.id
|
||||
}
|
||||
|
||||
fn push_edit(&mut self, edit: &EditOperation) {
|
||||
self.transaction.edit_ids.push(edit.timestamp.local());
|
||||
self.transaction.end.observe(edit.timestamp.local());
|
||||
fn push_edit(&mut self, edit_operation: &EditOperation) {
|
||||
self.transaction
|
||||
.edit_ids
|
||||
.push(edit_operation.timestamp.local());
|
||||
self.transaction
|
||||
.end
|
||||
.observe(edit_operation.timestamp.local());
|
||||
|
||||
let mut other_ranges = edit.ranges.iter().peekable();
|
||||
let mut edits = edit_operation
|
||||
.ranges
|
||||
.iter()
|
||||
.zip(edit_operation.new_text.iter())
|
||||
.peekable();
|
||||
let mut new_ranges = Vec::new();
|
||||
let insertion_len = edit.new_text.as_ref().map_or(0, |t| t.len());
|
||||
let mut delta = 0;
|
||||
|
||||
for mut self_range in self.transaction.ranges.iter().cloned() {
|
||||
self_range.start += delta;
|
||||
self_range.end += delta;
|
||||
|
||||
while let Some(other_range) = other_ranges.peek() {
|
||||
while let Some((other_range, new_text)) = edits.peek() {
|
||||
let insertion_len = new_text.as_ref().map_or(0, |t| t.len());
|
||||
let mut other_range = (*other_range).clone();
|
||||
other_range.start += delta;
|
||||
other_range.end += delta;
|
||||
|
||||
if other_range.start <= self_range.end {
|
||||
other_ranges.next().unwrap();
|
||||
edits.next().unwrap();
|
||||
delta += insertion_len;
|
||||
|
||||
if other_range.end < self_range.start {
|
||||
|
@ -129,7 +137,8 @@ impl HistoryEntry {
|
|||
new_ranges.push(self_range);
|
||||
}
|
||||
|
||||
for other_range in other_ranges {
|
||||
for (other_range, new_text) in edits {
|
||||
let insertion_len = new_text.as_ref().map_or(0, |t| t.len());
|
||||
new_ranges.push(other_range.start + delta..other_range.end + delta + insertion_len);
|
||||
delta += insertion_len;
|
||||
}
|
||||
|
@ -515,7 +524,7 @@ pub struct EditOperation {
|
|||
pub timestamp: InsertionTimestamp,
|
||||
pub version: clock::Global,
|
||||
pub ranges: Vec<Range<FullOffset>>,
|
||||
pub new_text: Option<String>,
|
||||
pub new_text: Vec<Option<Arc<str>>>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
|
@ -606,20 +615,30 @@ impl Buffer {
|
|||
self.history.group_interval
|
||||
}
|
||||
|
||||
pub fn edit<R, I, S, T>(&mut self, ranges: R, new_text: T) -> Operation
|
||||
pub fn edit<S, T>(&mut self, range: Range<S>, new_text: T) -> Operation
|
||||
where
|
||||
S: ToOffset,
|
||||
T: Into<Arc<str>>,
|
||||
{
|
||||
self.edit_batched([(range, new_text)])
|
||||
}
|
||||
|
||||
pub fn edit_batched<R, I, S, T>(&mut self, edits: R) -> Operation
|
||||
where
|
||||
R: IntoIterator<IntoIter = I>,
|
||||
I: ExactSizeIterator<Item = Range<S>>,
|
||||
I: ExactSizeIterator<Item = (Range<S>, T)>,
|
||||
S: ToOffset,
|
||||
T: Into<String>,
|
||||
T: Into<Arc<str>>,
|
||||
{
|
||||
let new_text = new_text.into();
|
||||
let new_text_len = new_text.len();
|
||||
let new_text = if new_text_len > 0 {
|
||||
Some(new_text)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let edits = edits.into_iter().map(|(range, new_text)| {
|
||||
let possibly_empty_arc_str = new_text.into();
|
||||
let non_empty_text = if possibly_empty_arc_str.len() > 0 {
|
||||
Some(possibly_empty_arc_str)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
(range, non_empty_text)
|
||||
});
|
||||
|
||||
self.start_transaction();
|
||||
let timestamp = InsertionTimestamp {
|
||||
|
@ -627,8 +646,7 @@ impl Buffer {
|
|||
local: self.local_clock.tick().value,
|
||||
lamport: self.lamport_clock.tick().value,
|
||||
};
|
||||
let operation =
|
||||
Operation::Edit(self.apply_local_edit(ranges.into_iter(), new_text, timestamp));
|
||||
let operation = Operation::Edit(self.apply_local_edit(edits, timestamp));
|
||||
|
||||
self.history.push(operation.clone());
|
||||
self.history.push_undo(operation.local_timestamp());
|
||||
|
@ -637,35 +655,35 @@ impl Buffer {
|
|||
operation
|
||||
}
|
||||
|
||||
fn apply_local_edit<S: ToOffset>(
|
||||
fn apply_local_edit<S: ToOffset, T: Into<Arc<str>>>(
|
||||
&mut self,
|
||||
ranges: impl ExactSizeIterator<Item = Range<S>>,
|
||||
new_text: Option<String>,
|
||||
edits: impl ExactSizeIterator<Item = (Range<S>, Option<T>)>,
|
||||
timestamp: InsertionTimestamp,
|
||||
) -> EditOperation {
|
||||
let mut edits = Patch::default();
|
||||
let mut edits_patch = Patch::default();
|
||||
let mut edit_op = EditOperation {
|
||||
timestamp,
|
||||
version: self.version(),
|
||||
ranges: Vec::with_capacity(ranges.len()),
|
||||
new_text: None,
|
||||
ranges: Vec::with_capacity(edits.len()),
|
||||
new_text: Vec::with_capacity(edits.len()),
|
||||
};
|
||||
let mut new_insertions = Vec::new();
|
||||
let mut insertion_offset = 0;
|
||||
|
||||
let mut ranges = ranges
|
||||
.map(|range| range.start.to_offset(&*self)..range.end.to_offset(&*self))
|
||||
let mut ranges = edits
|
||||
.map(|(range, new_text)| (range.to_offset(&*self), new_text))
|
||||
.peekable();
|
||||
|
||||
let mut new_ropes =
|
||||
RopeBuilder::new(self.visible_text.cursor(0), self.deleted_text.cursor(0));
|
||||
let mut old_fragments = self.fragments.cursor::<FragmentTextSummary>();
|
||||
let mut new_fragments =
|
||||
old_fragments.slice(&ranges.peek().unwrap().start, Bias::Right, &None);
|
||||
old_fragments.slice(&ranges.peek().unwrap().0.start, Bias::Right, &None);
|
||||
new_ropes.push_tree(new_fragments.summary().text);
|
||||
|
||||
let mut fragment_start = old_fragments.start().visible;
|
||||
for range in ranges {
|
||||
for (range, new_text) in ranges {
|
||||
let new_text = new_text.map(|t| t.into());
|
||||
let fragment_end = old_fragments.end(&None).visible;
|
||||
|
||||
// If the current fragment ends before this range, then jump ahead to the first fragment
|
||||
|
@ -708,7 +726,7 @@ impl Buffer {
|
|||
// Insert the new text before any existing fragments within the range.
|
||||
if let Some(new_text) = new_text.as_deref() {
|
||||
let new_start = new_fragments.summary().text.visible;
|
||||
edits.push(Edit {
|
||||
edits_patch.push(Edit {
|
||||
old: fragment_start..fragment_start,
|
||||
new: new_start..new_start + new_text.len(),
|
||||
});
|
||||
|
@ -750,7 +768,7 @@ impl Buffer {
|
|||
if intersection.len > 0 {
|
||||
if fragment.visible && !intersection.visible {
|
||||
let new_start = new_fragments.summary().text.visible;
|
||||
edits.push(Edit {
|
||||
edits_patch.push(Edit {
|
||||
old: fragment_start..intersection_end,
|
||||
new: new_start..new_start,
|
||||
});
|
||||
|
@ -767,6 +785,7 @@ impl Buffer {
|
|||
|
||||
let full_range_end = FullOffset(range.end + old_fragments.start().deleted);
|
||||
edit_op.ranges.push(full_range_start..full_range_end);
|
||||
edit_op.new_text.push(new_text);
|
||||
}
|
||||
|
||||
// If the current fragment has been partially consumed, then consume the rest of it
|
||||
|
@ -794,8 +813,7 @@ impl Buffer {
|
|||
self.snapshot.insertions.edit(new_insertions, &());
|
||||
self.snapshot.visible_text = visible_text;
|
||||
self.snapshot.deleted_text = deleted_text;
|
||||
self.subscriptions.publish_mut(&edits);
|
||||
edit_op.new_text = new_text;
|
||||
self.subscriptions.publish_mut(&edits_patch);
|
||||
edit_op
|
||||
}
|
||||
|
||||
|
@ -822,7 +840,7 @@ impl Buffer {
|
|||
self.apply_remote_edit(
|
||||
&edit.version,
|
||||
&edit.ranges,
|
||||
edit.new_text.as_deref(),
|
||||
&edit.new_text,
|
||||
edit.timestamp,
|
||||
);
|
||||
self.snapshot.version.observe(edit.timestamp.local());
|
||||
|
@ -852,14 +870,15 @@ impl Buffer {
|
|||
&mut self,
|
||||
version: &clock::Global,
|
||||
ranges: &[Range<FullOffset>],
|
||||
new_text: Option<&str>,
|
||||
new_text: &[Option<Arc<str>>],
|
||||
timestamp: InsertionTimestamp,
|
||||
) {
|
||||
if ranges.is_empty() {
|
||||
return;
|
||||
}
|
||||
|
||||
let mut edits = Patch::default();
|
||||
let edits = ranges.into_iter().zip(new_text.into_iter());
|
||||
let mut edits_patch = Patch::default();
|
||||
let cx = Some(version.clone());
|
||||
let mut new_insertions = Vec::new();
|
||||
let mut insertion_offset = 0;
|
||||
|
@ -874,7 +893,7 @@ impl Buffer {
|
|||
new_ropes.push_tree(new_fragments.summary().text);
|
||||
|
||||
let mut fragment_start = old_fragments.start().0.full_offset();
|
||||
for range in ranges {
|
||||
for (range, new_text) in edits {
|
||||
let fragment_end = old_fragments.end(&cx).0.full_offset();
|
||||
|
||||
// If the current fragment ends before this range, then jump ahead to the first fragment
|
||||
|
@ -950,7 +969,7 @@ impl Buffer {
|
|||
old_start += fragment_start.0 - old_fragments.start().0.full_offset().0;
|
||||
}
|
||||
let new_start = new_fragments.summary().text.visible;
|
||||
edits.push(Edit {
|
||||
edits_patch.push(Edit {
|
||||
old: old_start..old_start,
|
||||
new: new_start..new_start + new_text.len(),
|
||||
});
|
||||
|
@ -995,7 +1014,7 @@ impl Buffer {
|
|||
let old_start = old_fragments.start().1
|
||||
+ (fragment_start.0 - old_fragments.start().0.full_offset().0);
|
||||
let new_start = new_fragments.summary().text.visible;
|
||||
edits.push(Edit {
|
||||
edits_patch.push(Edit {
|
||||
old: old_start..old_start + intersection.len,
|
||||
new: new_start..new_start,
|
||||
});
|
||||
|
@ -1036,7 +1055,7 @@ impl Buffer {
|
|||
self.snapshot.visible_text = visible_text;
|
||||
self.snapshot.deleted_text = deleted_text;
|
||||
self.snapshot.insertions.edit(new_insertions, &());
|
||||
self.subscriptions.publish_mut(&edits);
|
||||
self.subscriptions.publish_mut(&edits_patch);
|
||||
}
|
||||
|
||||
fn apply_undo(&mut self, undo: &UndoOperation) -> Result<()> {
|
||||
|
@ -1416,31 +1435,32 @@ impl Buffer {
|
|||
pub fn randomly_edit<T>(
|
||||
&mut self,
|
||||
rng: &mut T,
|
||||
old_range_count: usize,
|
||||
) -> (Vec<Range<usize>>, String, Operation)
|
||||
edit_count: usize,
|
||||
) -> (Vec<(Range<usize>, Arc<str>)>, Operation)
|
||||
where
|
||||
T: rand::Rng,
|
||||
{
|
||||
let mut old_ranges: Vec<Range<usize>> = Vec::new();
|
||||
for _ in 0..old_range_count {
|
||||
let last_end = old_ranges.last().map_or(0, |last_range| last_range.end + 1);
|
||||
if last_end > self.len() {
|
||||
let mut edits: Vec<(Range<usize>, Arc<str>)> = Vec::new();
|
||||
let mut last_end = None;
|
||||
for _ in 0..edit_count {
|
||||
if last_end.map_or(false, |last_end| last_end >= self.len()) {
|
||||
break;
|
||||
}
|
||||
old_ranges.push(self.random_byte_range(last_end, rng));
|
||||
let new_start = last_end.map_or(0, |last_end| last_end + 1);
|
||||
let range = self.random_byte_range(new_start, rng);
|
||||
last_end = Some(range.end);
|
||||
|
||||
let new_text_len = rng.gen_range(0..10);
|
||||
let new_text: String = crate::random_char_iter::RandomCharIter::new(&mut *rng)
|
||||
.take(new_text_len)
|
||||
.collect();
|
||||
|
||||
edits.push((range, new_text.into()));
|
||||
}
|
||||
let new_text_len = rng.gen_range(0..10);
|
||||
let new_text: String = crate::random_char_iter::RandomCharIter::new(&mut *rng)
|
||||
.take(new_text_len)
|
||||
.collect();
|
||||
log::info!(
|
||||
"mutating buffer {} at {:?}: {:?}",
|
||||
self.replica_id,
|
||||
old_ranges,
|
||||
new_text
|
||||
);
|
||||
let op = self.edit(old_ranges.iter().cloned(), new_text.as_str());
|
||||
(old_ranges, new_text, op)
|
||||
|
||||
log::info!("mutating buffer {} with {:?}", self.replica_id, edits);
|
||||
let op = self.edit_batched(edits.iter().cloned());
|
||||
(edits, op)
|
||||
}
|
||||
|
||||
pub fn randomly_undo_redo(&mut self, rng: &mut impl rand::Rng) -> Vec<Operation> {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue