@@ -5,7 +5,10 @@ use super::fold_map::{
OutputOffset as InputOffset, OutputPoint as InputPoint, Snapshot as InputSnapshot,
};
use crate::{settings::StyleId, util::Bias};
-use std::{mem, ops::Range};
+use std::{
+ mem,
+ ops::{AddAssign, Range},
+};
pub struct TabMap(Mutex<Snapshot>);
@@ -27,11 +30,15 @@ impl TabMap {
let mut output_edits = Vec::with_capacity(input_edits.len());
for input_edit in input_edits {
+ let old_start = input_edit.old_bytes.start.to_point(&old_snapshot.input);
+ let old_end = input_edit.old_bytes.end.to_point(&old_snapshot.input);
+ let new_start = input_edit.new_bytes.start.to_point(&new_snapshot.input);
+ let new_end = input_edit.new_bytes.end.to_point(&new_snapshot.input);
output_edits.push(Edit {
- old_bytes: old_snapshot.to_output_offset(input_edit.old_bytes.start)
- ..old_snapshot.to_output_offset(input_edit.old_bytes.end),
- new_bytes: new_snapshot.to_output_offset(input_edit.new_bytes.start)
- ..new_snapshot.to_output_offset(input_edit.new_bytes.end),
+ old_lines: old_snapshot.to_output_point(old_start)
+ ..old_snapshot.to_output_point(old_end),
+ new_lines: new_snapshot.to_output_point(new_start)
+ ..new_snapshot.to_output_point(new_end),
});
}
@@ -253,24 +260,16 @@ impl OutputPoint {
}
}
-#[derive(Clone, Debug, PartialEq, Eq)]
-pub struct Edit {
- pub old_bytes: Range<OutputOffset>,
- pub new_bytes: Range<OutputOffset>,
-}
-
-impl Edit {
- pub fn delta(&self) -> isize {
- self.inserted_bytes() as isize - self.deleted_bytes() as isize
- }
-
- pub fn deleted_bytes(&self) -> usize {
- self.old_bytes.end.0 - self.old_bytes.start.0
+impl AddAssign<Self> for OutputPoint {
+ fn add_assign(&mut self, rhs: Self) {
+ self.0 += rhs.0;
}
+}
- pub fn inserted_bytes(&self) -> usize {
- self.new_bytes.end.0 - self.new_bytes.start.0
- }
+#[derive(Clone, Debug, PartialEq, Eq)]
+pub struct Edit {
+ pub old_lines: Range<OutputPoint>,
+ pub new_lines: Range<OutputPoint>,
}
#[derive(Clone, Debug, Default, Eq, PartialEq)]
@@ -1,15 +1,17 @@
use super::tab_map::{
- Edit as InputEdit, OutputOffset as InputOffset, Snapshot as InputSnapshot, TextSummary,
+ Edit as InputEdit, OutputOffset as InputOffset, OutputPoint as InputPoint,
+ Snapshot as InputSnapshot, TextSummary,
};
use crate::{
editor::Point,
sum_tree::{self, SumTree},
+ util::Bias,
};
use gpui::{font_cache::FamilyId, AppContext, FontCache, FontSystem, Task};
use parking_lot::Mutex;
use postage::{prelude::Sink, watch};
use smol::channel;
-use std::sync::Arc;
+use std::{ops::Range, sync::Arc};
#[derive(Copy, Clone, Debug, Default, Eq, Ord, PartialOrd, PartialEq)]
pub struct OutputPoint(super::Point);
@@ -148,8 +150,8 @@ impl BackgroundWrapper {
mut snapshots_tx: watch::Sender<Snapshot>,
) {
let edit = InputEdit {
- old_bytes: InputOffset(0)..InputOffset(0),
- new_bytes: InputOffset(0)..snapshot.len(),
+ old_lines: Default::default()..Default::default(),
+ new_lines: Default::default()..snapshot.max_point(),
};
self.sync(snapshot, vec![edit]);
if snapshots_tx.send(self.snapshot.clone()).await.is_err() {
@@ -164,85 +166,108 @@ impl BackgroundWrapper {
}
}
- fn sync(&mut self, snapshot: InputSnapshot, edits: Vec<InputEdit>) {
+ fn sync(&mut self, new_snapshot: InputSnapshot, edits: Vec<InputEdit>) {
+ if edits.is_empty() {
+ return;
+ }
+
let font_id = self
.font_cache
- .select_font(self.config.font_family, &Default::default());
+ .select_font(self.config.font_family, &Default::default())
+ .unwrap();
let font_size = self.config.font_size;
let wrap_width = self.config.wrap_width;
- let mut new_transforms = SumTree::new();
+ let mut new_transforms;
{
- // let mut old_cursor = self.snapshot.transforms.cursor::<DisplayPoint, ()>();
- // let mut position = DisplayPoint::zero();
- // for edit in edits {
- // let old_start = DisplayPoint::new(
- // edit.old_bytes.start.to_display_point(&self.snapshot).row(),
- // 0,
- // );
- // let old_end = DisplayPoint::new(
- // edit.old_bytes.end.to_display_point(&self.snapshot).row() + 1,
- // 0,
- // );
- // let new_start =
- // DisplayPoint::new(edit.new_bytes.start.to_display_point(&snapshot).row(), 0);
- // let new_end =
- // DisplayPoint::new(edit.new_bytes.end.to_display_point(&snapshot).row() + 1, 0);
-
- // if position > old_cursor.seek_start() && old_start >= old_cursor.seek_end(&()) {
- // old_cursor.next(&());
- // }
-
- // let prefix = old_cursor.slice(&old_start, Bias::Right, &());
- // new_transforms.push_tree(prefix, &());
- // new_transforms.push(
- // Transform::isomorphic(
- // self.snapshot
- // .folds_snapshot
- // .text_summary_for_range(position..old_start),
- // ),
- // &(),
- // );
-
- // let mut row = new_start.row();
- // let mut line = String::new();
- // 'outer: for chunk in snapshot.chunks_at(snapshot.to_display_offset(new_start)) {
- // for (ix, line_chunk) in chunk.split('\n').enumerate() {
- // if ix > 0 {
- // let mut prev_boundary_ix = 0;
- // for boundary_ix in self
- // .font_system
- // .wrap_line(&line, font_id, font_size, wrap_width)
- // {
- // let wrapped = &line[prev_boundary_ix..boundary_ix];
- // new_transforms
- // .push(Transform::isomorphic(TextSummary::from(wrapped)));
- // new_transforms.push(Transform::newline());
- // prev_boundary_ix = boundary_ix;
- // }
-
- // line.clear();
- // row += 1;
- // if row == new_end.row() {
- // break 'outer;
- // }
- // }
-
- // line.push_str(line_chunk);
- // }
- // }
-
- // old_cursor.seek_forward(&old_end, Bias::Right, &());
- // position = old_end;
- // }
-
- // if position > old_cursor.seek_start() && old_start >= old_cursor.seek_end(&()) {
- // old_cursor.next(&());
- // }
+ struct RowEdit {
+ old_rows: Range<u32>,
+ new_rows: Range<u32>,
+ }
+
+ let mut edits = edits
+ .into_iter()
+ .map(|edit| RowEdit {
+ old_rows: edit.old_lines.start.row()..edit.old_lines.end.row() + 1,
+ new_rows: edit.new_lines.start.row()..edit.new_lines.end.row() + 1,
+ })
+ .peekable();
+ let mut old_cursor = self.snapshot.transforms.cursor::<InputPoint, ()>();
+
+ new_transforms = old_cursor.slice(
+ &InputPoint::new(edits.peek().unwrap().old_rows.start, 0),
+ Bias::Right,
+ &(),
+ );
+
+ for edit in edits {
+ if edit.new_rows.start > new_transforms.summary().input.row() {
+ new_transforms.push(
+ Transform::isomorphic(new_snapshot.input.text_summary_for_rows(
+ new_transforms.summary().input.row()..edit.new_rows.start,
+ )),
+ &(),
+ );
+ }
+
+ let mut row = edit.new_rows.start;
+ let mut line = String::new();
+ 'outer: for chunk in new_snapshot.chunks_at(InputPoint::new(row, 0)) {
+ for (ix, line_chunk) in chunk.split('\n').enumerate() {
+ if ix > 0 {
+ let mut prev_boundary_ix = 0;
+ for boundary_ix in self
+ .font_system
+ .wrap_line(&line, font_id, font_size, wrap_width)
+ {
+ let wrapped = &line[prev_boundary_ix..boundary_ix];
+ new_transforms
+ .push(Transform::isomorphic(TextSummary::from(wrapped)), &());
+ new_transforms.push(Transform::newline(), &());
+ prev_boundary_ix = boundary_ix;
+ }
+
+ line.clear();
+ row += 1;
+ if row == edit.new_rows.end {
+ break 'outer;
+ }
+ }
+
+ line.push_str(line_chunk);
+ }
+ }
+
+ old_cursor.seek_forward(&edit.old_rows.end, Bias::Right, &());
+ if let Some(next_edit) = edits.peek() {
+ if next_edit.old_rows.start > old_cursor.seek_end(&()).row() {
+ new_transforms.push(
+ Transform::isomorphic(self.snapshot.input.text_summary_for_rows(
+ edit.old_rows.end..old_cursor.seek_end(&()).row(),
+ )),
+ &(),
+ );
+ old_cursor.next(&());
+ new_transforms.push_tree(
+ old_cursor.slice(&next_edit.old_rows.start, Bias::Right, &()),
+ &(),
+ );
+ }
+ } else {
+ new_transforms.push(
+ Transform::isomorphic(self.snapshot.input.text_summary_for_rows(
+ edit.old_rows.end..old_cursor.seek_end(&()).row(),
+ )),
+ &(),
+ );
+ old_cursor.next(&());
+ new_transforms.push_tree(old_cursor.suffix(&()), &());
+ }
+ }
}
self.snapshot.transforms = new_transforms;
- self.snapshot.version = snapshot.version();
+ self.snapshot.version = new_snapshot.version();
}
}
@@ -303,9 +328,9 @@ impl sum_tree::Summary for TransformSummary {
}
}
-impl<'a> sum_tree::Dimension<'a, TransformSummary> for Point {
+impl<'a> sum_tree::Dimension<'a, TransformSummary> for InputPoint {
fn add_summary(&mut self, summary: &'a TransformSummary, _: &()) {
- *self += &summary.input.lines;
+ *self += &InputPoint(summary.input.lines);
}
}
@@ -367,8 +392,8 @@ mod tests {
font_system.clone(),
);
let edit = InputEdit {
- old_bytes: InputOffset(0)..InputOffset(0),
- new_bytes: InputOffset(0)..tabs_snapshot.len(),
+ old_lines: Default::default()..Default::default(),
+ new_lines: Default::default()..tabs_snapshot.max_point(),
};
wrapper.sync(tabs_snapshot.clone(), vec![edit]);