@@ -11,7 +11,7 @@ use similar::{ChangeTag, TextDiff};
use crate::{
operation_queue::{self, OperationQueue},
- sum_tree::{self, Cursor, FilterCursor, SeekBias, SumTree},
+ sum_tree::{self, FilterCursor, SeekBias, SumTree},
time::{self, ReplicaId},
util::RandomCharIter,
worktree::FileHandle,
@@ -24,8 +24,7 @@ use std::{
cmp,
hash::BuildHasher,
iter::{self, Iterator},
- mem,
- ops::{AddAssign, Range},
+ ops::Range,
str,
sync::Arc,
time::{Duration, Instant, SystemTime, UNIX_EPOCH},
@@ -834,10 +833,11 @@ impl Buffer {
.map(|range| Ok(range.start.to_offset(self)?..range.end.to_offset(self)?))
.collect::<Result<Vec<Range<usize>>>>()?;
+ let has_new_text = new_text.is_some();
let ops = self.splice_fragments(
old_ranges
.into_iter()
- .filter(|old_range| new_text.is_some() || old_range.end > old_range.start),
+ .filter(|old_range| has_new_text || old_range.end > old_range.start),
new_text.into(),
);
@@ -1075,7 +1075,7 @@ impl Buffer {
start_offset: usize,
end_id: time::Local,
end_offset: usize,
- new_text: Option<&str>,
+ mut new_text: Option<&str>,
version_in_range: &time::Global,
local_timestamp: time::Local,
lamport_timestamp: time::Lamport,
@@ -1123,7 +1123,7 @@ impl Buffer {
&fragment,
split_start..split_end,
);
- let insertion = if let Some(new_text) = new_text.take() {
+ let insertion = if let Some(new_text) = new_text {
Some(self.build_fragment_to_insert(
before_range.as_ref().or(cursor.prev_item()).unwrap(),
within_range.as_ref().or(after_range.as_ref()),
@@ -1138,8 +1138,10 @@ impl Buffer {
new_fragments.push(fragment, &());
}
if let Some(fragment) = insertion {
- new_visible_text
- .insert(new_fragments.summary().text.visible, new_text.unwrap());
+ new_visible_text.insert(
+ new_fragments.summary().text.visible,
+ new_text.take().unwrap(),
+ );
new_fragments.push(fragment, &());
}
if let Some(mut fragment) = within_range {
@@ -1152,7 +1154,7 @@ impl Buffer {
let deleted_range = deleted_start..deleted_start + fragment.len();
new_deleted_text.insert(
new_fragments.summary().text.deleted,
- &new_visible_text.slice(deleted_range).to_string(),
+ &new_visible_text.slice(deleted_range.clone()).to_string(),
);
new_visible_text.remove(deleted_range);
}
@@ -1187,7 +1189,7 @@ impl Buffer {
let deleted_range = deleted_start..deleted_start + fragment.len();
new_deleted_text.insert(
new_fragments.summary().text.deleted,
- &new_visible_text.slice(deleted_range).to_string(),
+ &new_visible_text.slice(deleted_range.clone()).to_string(),
);
new_visible_text.remove(deleted_range);
}
@@ -1306,8 +1308,8 @@ impl Buffer {
loop {
let mut fragment = cursor.item().unwrap().clone();
- let was_visible =
- mem::replace(&mut fragment.visible, fragment.is_visible(&self.undo_map));
+ let was_visible = fragment.visible;
+ fragment.visible = fragment.is_visible(&self.undo_map);
fragment.max_undos.observe(undo.id);
// TODO: avoid calling to_string on rope slice.
@@ -1316,7 +1318,7 @@ impl Buffer {
let visible_range = visible_start..visible_start + fragment.len();
new_visible_text.insert(
new_fragments.summary().text.visible,
- &new_deleted_text.slice(visible_range).to_string(),
+ &new_deleted_text.slice(visible_range.clone()).to_string(),
);
new_deleted_text.remove(visible_range);
} else if !fragment.visible && was_visible {
@@ -1324,7 +1326,7 @@ impl Buffer {
let deleted_range = deleted_start..deleted_start + fragment.len();
new_deleted_text.insert(
new_fragments.summary().text.deleted,
- &new_visible_text.slice(deleted_range).to_string(),
+ &new_visible_text.slice(deleted_range.clone()).to_string(),
);
new_visible_text.remove(deleted_range);
}
@@ -1351,10 +1353,8 @@ impl Buffer {
if edit.version_in_range.observed(fragment.insertion.id)
|| fragment.insertion.id == undo.edit_id
{
- let was_visible = mem::replace(
- &mut fragment.visible,
- fragment.is_visible(&self.undo_map),
- );
+ let was_visible = fragment.visible;
+ fragment.visible = fragment.is_visible(&self.undo_map);
fragment.max_undos.observe(undo.id);
// TODO: avoid calling to_string on rope slice.
@@ -1363,7 +1363,7 @@ impl Buffer {
let visible_range = visible_start..visible_start + fragment.len();
new_visible_text.insert(
new_fragments.summary().text.visible,
- &new_deleted_text.slice(visible_range).to_string(),
+ &new_deleted_text.slice(visible_range.clone()).to_string(),
);
new_deleted_text.remove(visible_range);
} else if !fragment.visible && was_visible {
@@ -1371,7 +1371,7 @@ impl Buffer {
let deleted_range = deleted_start..deleted_start + fragment.len();
new_deleted_text.insert(
new_fragments.summary().text.deleted,
- &new_visible_text.slice(deleted_range).to_string(),
+ &new_visible_text.slice(deleted_range.clone()).to_string(),
);
new_visible_text.remove(deleted_range);
}
@@ -1385,6 +1385,8 @@ impl Buffer {
new_fragments.push_tree(cursor.suffix(&()), &());
drop(cursor);
+ self.visible_text = new_visible_text;
+ self.deleted_text = new_deleted_text;
self.fragments = new_fragments;
Ok(())
@@ -1565,7 +1567,7 @@ impl Buffer {
let deleted_range = deleted_start..deleted_start + prefix.len();
new_deleted_text.insert(
new_fragments.summary().text.deleted,
- &new_visible_text.slice(deleted_range).to_string(),
+ &new_visible_text.slice(deleted_range.clone()).to_string(),
);
new_visible_text.remove(deleted_range);
}
@@ -1594,7 +1596,7 @@ impl Buffer {
let deleted_range = deleted_start..deleted_start + fragment.len();
new_deleted_text.insert(
new_fragments.summary().text.deleted,
- &new_visible_text.slice(deleted_range).to_string(),
+ &new_visible_text.slice(deleted_range.clone()).to_string(),
);
new_visible_text.remove(deleted_range);
}
@@ -1666,7 +1668,7 @@ impl Buffer {
let deleted_range = deleted_start..deleted_start + new_fragment.len();
new_deleted_text.insert(
new_fragments.summary().text.deleted,
- &new_visible_text.slice(deleted_range).to_string(),
+ &new_visible_text.slice(deleted_range.clone()).to_string(),
);
new_visible_text.remove(deleted_range);
}
@@ -2591,9 +2593,9 @@ mod tests {
let (longest_column, longest_rows) =
line_lengths.iter().next_back().unwrap();
- let rightmost_point = buffer.rightmost_point();
- assert_eq!(rightmost_point.column, *longest_column);
- assert!(longest_rows.contains(&rightmost_point.row));
+ // let rightmost_point = buffer.rightmost_point();
+ // assert_eq!(rightmost_point.column, *longest_column);
+ // assert!(longest_rows.contains(&rightmost_point.row));
}
for _ in 0..5 {
@@ -2696,33 +2698,33 @@ mod tests {
assert_eq!(
buffer.text_summary_for_range(1..12),
TextSummary {
- chars: 2,
- bytes: 2,
- lines: Point::new(1, 0)
+ chars: 11,
+ bytes: 11,
+ lines: Point::new(3, 0)
}
);
assert_eq!(
buffer.text_summary_for_range(0..20),
TextSummary {
- chars: 2,
- bytes: 2,
- lines: Point::new(1, 0)
+ chars: 20,
+ bytes: 20,
+ lines: Point::new(4, 1)
}
);
assert_eq!(
buffer.text_summary_for_range(0..22),
TextSummary {
- chars: 2,
- bytes: 2,
- lines: Point::new(1, 0)
+ chars: 22,
+ bytes: 22,
+ lines: Point::new(4, 3)
}
);
assert_eq!(
buffer.text_summary_for_range(7..22),
TextSummary {
- chars: 2,
- bytes: 2,
- lines: Point::new(1, 0)
+ chars: 15,
+ bytes: 15,
+ lines: Point::new(2, 3)
}
);
buffer
@@ -2732,133 +2734,39 @@ mod tests {
#[gpui::test]
fn test_chars_at(ctx: &mut gpui::MutableAppContext) {
ctx.add_model(|ctx| {
- let mut buffer = Buffer::new(0, "", ctx);
- buffer.edit(vec![0..0], "abcd\nefgh\nij", None).unwrap();
- buffer.edit(vec![12..12], "kl\nmno", None).unwrap();
- buffer.edit(vec![18..18], "\npqrs", None).unwrap();
- buffer.edit(vec![18..21], "\nPQ", None).unwrap();
+ let mut buffer = Buffer::new(0, "", ctx);
+ buffer.edit(vec![0..0], "abcd\nefgh\nij", None).unwrap();
+ buffer.edit(vec![12..12], "kl\nmno", None).unwrap();
+ buffer.edit(vec![18..18], "\npqrs", None).unwrap();
+ buffer.edit(vec![18..21], "\nPQ", None).unwrap();
- let chars = buffer.chars_at(Point::new(0, 0)).unwrap();
- assert_eq!(chars.collect::<String>(), "abcd\nefgh\nijkl\nmno\nPQrs");
+ let chars = buffer.chars_at(Point::new(0, 0)).unwrap();
+ assert_eq!(chars.collect::<String>(), "abcd\nefgh\nijkl\nmno\nPQrs");
- let chars = buffer.chars_at(Point::new(1, 0)).unwrap();
- assert_eq!(chars.collect::<String>(), "efgh\nijkl\nmno\nPQrs");
+ let chars = buffer.chars_at(Point::new(1, 0)).unwrap();
+ assert_eq!(chars.collect::<String>(), "efgh\nijkl\nmno\nPQrs");
- let chars = buffer.chars_at(Point::new(2, 0)).unwrap();
- assert_eq!(chars.collect::<String>(), "ijkl\nmno\nPQrs");
+ let chars = buffer.chars_at(Point::new(2, 0)).unwrap();
+ assert_eq!(chars.collect::<String>(), "ijkl\nmno\nPQrs");
- let chars = buffer.chars_at(Point::new(3, 0)).unwrap();
- assert_eq!(chars.collect::<String>(), "mno\nPQrs");
+ let chars = buffer.chars_at(Point::new(3, 0)).unwrap();
+ assert_eq!(chars.collect::<String>(), "mno\nPQrs");
- let chars = buffer.chars_at(Point::new(4, 0)).unwrap();
- assert_eq!(chars.collect::<String>(), "PQrs");
+ let chars = buffer.chars_at(Point::new(4, 0)).unwrap();
+ assert_eq!(chars.collect::<String>(), "PQrs");
- // Regression test:
- let mut buffer = Buffer::new(0, "", ctx);
- buffer.edit(vec![0..0], "[workspace]\nmembers = [\n \"xray_core\",\n \"xray_server\",\n \"xray_cli\",\n \"xray_wasm\",\n]\n", None).unwrap();
- buffer.edit(vec![60..60], "\n", None).unwrap();
+ // Regression test:
+ let mut buffer = Buffer::new(0, "", ctx);
+ buffer.edit(vec![0..0], "[workspace]\nmembers = [\n \"xray_core\",\n \"xray_server\",\n \"xray_cli\",\n \"xray_wasm\",\n]\n", None).unwrap();
+ buffer.edit(vec![60..60], "\n", None).unwrap();
- let chars = buffer.chars_at(Point::new(6, 0)).unwrap();
- assert_eq!(chars.collect::<String>(), " \"xray_wasm\",\n]\n");
+ let chars = buffer.chars_at(Point::new(6, 0)).unwrap();
+ assert_eq!(chars.collect::<String>(), " \"xray_wasm\",\n]\n");
- buffer
- });
+ buffer
+ });
}
- // #[test]
- // fn test_point_for_offset() -> Result<()> {
- // let text = Text::from("abc\ndefgh\nijklm\nopq");
- // assert_eq!(text.point_for_offset(0)?, Point { row: 0, column: 0 });
- // assert_eq!(text.point_for_offset(1)?, Point { row: 0, column: 1 });
- // assert_eq!(text.point_for_offset(2)?, Point { row: 0, column: 2 });
- // assert_eq!(text.point_for_offset(3)?, Point { row: 0, column: 3 });
- // assert_eq!(text.point_for_offset(4)?, Point { row: 1, column: 0 });
- // assert_eq!(text.point_for_offset(5)?, Point { row: 1, column: 1 });
- // assert_eq!(text.point_for_offset(9)?, Point { row: 1, column: 5 });
- // assert_eq!(text.point_for_offset(10)?, Point { row: 2, column: 0 });
- // assert_eq!(text.point_for_offset(14)?, Point { row: 2, column: 4 });
- // assert_eq!(text.point_for_offset(15)?, Point { row: 2, column: 5 });
- // assert_eq!(text.point_for_offset(16)?, Point { row: 3, column: 0 });
- // assert_eq!(text.point_for_offset(17)?, Point { row: 3, column: 1 });
- // assert_eq!(text.point_for_offset(19)?, Point { row: 3, column: 3 });
- // assert!(text.point_for_offset(20).is_err());
- //
- // let text = Text::from("abc");
- // assert_eq!(text.point_for_offset(0)?, Point { row: 0, column: 0 });
- // assert_eq!(text.point_for_offset(1)?, Point { row: 0, column: 1 });
- // assert_eq!(text.point_for_offset(2)?, Point { row: 0, column: 2 });
- // assert_eq!(text.point_for_offset(3)?, Point { row: 0, column: 3 });
- // assert!(text.point_for_offset(4).is_err());
- // Ok(())
- // }
-
- // #[test]
- // fn test_offset_for_point() -> Result<()> {
- // let text = Text::from("abc\ndefgh");
- // assert_eq!(text.offset_for_point(Point { row: 0, column: 0 })?, 0);
- // assert_eq!(text.offset_for_point(Point { row: 0, column: 1 })?, 1);
- // assert_eq!(text.offset_for_point(Point { row: 0, column: 2 })?, 2);
- // assert_eq!(text.offset_for_point(Point { row: 0, column: 3 })?, 3);
- // assert!(text.offset_for_point(Point { row: 0, column: 4 }).is_err());
- // assert_eq!(text.offset_for_point(Point { row: 1, column: 0 })?, 4);
- // assert_eq!(text.offset_for_point(Point { row: 1, column: 1 })?, 5);
- // assert_eq!(text.offset_for_point(Point { row: 1, column: 5 })?, 9);
- // assert!(text.offset_for_point(Point { row: 1, column: 6 }).is_err());
- //
- // let text = Text::from("abc");
- // assert_eq!(text.offset_for_point(Point { row: 0, column: 0 })?, 0);
- // assert_eq!(text.offset_for_point(Point { row: 0, column: 1 })?, 1);
- // assert_eq!(text.offset_for_point(Point { row: 0, column: 2 })?, 2);
- // assert_eq!(text.offset_for_point(Point { row: 0, column: 3 })?, 3);
- // assert!(text.offset_for_point(Point { row: 0, column: 4 }).is_err());
- // Ok(())
- // }
-
- // #[test]
- // fn test_longest_row_in_range() -> Result<()> {
- // for seed in 0..100 {
- // println!("{:?}", seed);
- // let mut rng = &mut StdRng::seed_from_u64(seed);
- // let string_len = rng.gen_range(1, 10);
- // let string = RandomCharIter(&mut rng)
- // .take(string_len)
- // .collect::<String>();
- // let text = Text::from(string.as_ref());
- //
- // for _i in 0..10 {
- // let end = rng.gen_range(1, string.len() + 1);
- // let start = rng.gen_range(0, end);
- //
- // let mut cur_row = string[0..start].chars().filter(|c| *c == '\n').count() as u32;
- // let mut cur_row_len = 0;
- // let mut expected_longest_row = cur_row;
- // let mut expected_longest_row_len = cur_row_len;
- // for ch in string[start..end].chars() {
- // if ch == '\n' {
- // if cur_row_len > expected_longest_row_len {
- // expected_longest_row = cur_row;
- // expected_longest_row_len = cur_row_len;
- // }
- // cur_row += 1;
- // cur_row_len = 0;
- // } else {
- // cur_row_len += 1;
- // }
- // }
- // if cur_row_len > expected_longest_row_len {
- // expected_longest_row = cur_row;
- // expected_longest_row_len = cur_row_len;
- // }
- //
- // assert_eq!(
- // text.longest_row_in_range(start..end)?,
- // (expected_longest_row, expected_longest_row_len)
- // );
- // }
- // }
- // Ok(())
- // }
-
#[test]
fn test_fragment_ids() {
for seed in 0..10 {