From 5a33612f0f6c36cfd2a9dc396c53a59e8d145fc9 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Mon, 19 Jul 2021 19:34:41 +0200 Subject: [PATCH] WIP Co-Authored-By: Nathan Sobo --- zed/src/editor/display_map/tab_map.rs | 41 +++--- zed/src/editor/display_map/wrap_map.rs | 181 ++++++++++++++----------- 2 files changed, 123 insertions(+), 99 deletions(-) diff --git a/zed/src/editor/display_map/tab_map.rs b/zed/src/editor/display_map/tab_map.rs index 06962e5273cc342cc7c06f56bf3071642c730e9e..68ac493dd4ba3e91ced3961413e36372a5f185cd 100644 --- a/zed/src/editor/display_map/tab_map.rs +++ b/zed/src/editor/display_map/tab_map.rs @@ -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); @@ -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, - pub new_bytes: Range, -} - -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 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, + pub new_lines: Range, } #[derive(Clone, Debug, Default, Eq, PartialEq)] diff --git a/zed/src/editor/display_map/wrap_map.rs b/zed/src/editor/display_map/wrap_map.rs index f49e51ae3c3434bedc637d6d743812b87786e5cd..f6cf1c45b48613b65fa8c7fe7a8b9f4a4ed3f758 100644 --- a/zed/src/editor/display_map/wrap_map.rs +++ b/zed/src/editor/display_map/wrap_map.rs @@ -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, ) { 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) { + fn sync(&mut self, new_snapshot: InputSnapshot, edits: Vec) { + 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::(); - // 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, + new_rows: Range, + } + + 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::(); + + 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]);