diff --git a/crates/editor/src/display_map.rs b/crates/editor/src/display_map.rs index 5ec8d90121..67dbb34d5d 100644 --- a/crates/editor/src/display_map.rs +++ b/crates/editor/src/display_map.rs @@ -4,14 +4,18 @@ mod patch; mod tab_map; mod wrap_map; +use block_map::{BlockId, BlockMap, BlockPoint, BlockProperties}; +use buffer::Rope; use fold_map::{FoldMap, ToFoldPoint as _}; use gpui::{fonts::FontId, Entity, ModelContext, ModelHandle}; use language::{Anchor, Buffer, Point, ToOffset, ToPoint}; -use std::ops::Range; +use std::{collections::HashSet, ops::Range}; use sum_tree::Bias; use tab_map::TabMap; use wrap_map::WrapMap; -pub use wrap_map::{BufferRows, HighlightedChunks}; + +pub use block_map::HighlightedChunks; +pub use wrap_map::BufferRows; pub trait ToDisplayPoint { fn to_display_point(&self, map: &DisplayMapSnapshot, bias: Bias) -> DisplayPoint; @@ -22,6 +26,7 @@ pub struct DisplayMap { fold_map: FoldMap, tab_map: TabMap, wrap_map: ModelHandle, + block_map: BlockMap, } impl Entity for DisplayMap { @@ -39,28 +44,32 @@ impl DisplayMap { ) -> Self { let (fold_map, snapshot) = FoldMap::new(buffer.clone(), cx); let (tab_map, snapshot) = TabMap::new(snapshot, tab_size); - let (wrap_map, _) = WrapMap::new(snapshot, font_id, font_size, wrap_width, cx); + let (wrap_map, snapshot) = WrapMap::new(snapshot, font_id, font_size, wrap_width, cx); + let block_map = BlockMap::new(buffer.clone(), snapshot); cx.observe(&wrap_map, |_, _, cx| cx.notify()).detach(); DisplayMap { buffer, fold_map, tab_map, wrap_map, + block_map, } } pub fn snapshot(&self, cx: &mut ModelContext) -> DisplayMapSnapshot { let (folds_snapshot, edits) = self.fold_map.read(cx); let (tabs_snapshot, edits) = self.tab_map.sync(folds_snapshot.clone(), edits); - let (wraps_snapshot, _) = self + let (wraps_snapshot, edits) = self .wrap_map .update(cx, |map, cx| map.sync(tabs_snapshot.clone(), edits, cx)); + let blocks_snapshot = self.block_map.read(wraps_snapshot.clone(), edits, cx); DisplayMapSnapshot { buffer_snapshot: self.buffer.read(cx).snapshot(), folds_snapshot, tabs_snapshot, wraps_snapshot, + blocks_snapshot, } } @@ -94,6 +103,34 @@ impl DisplayMap { .update(cx, |map, cx| map.sync(snapshot, edits, cx)); } + pub fn insert_blocks( + &mut self, + blocks: impl IntoIterator>, + cx: &mut ModelContext, + ) -> Vec + where + P: ToOffset + Clone, + T: Into + Clone, + { + let (snapshot, edits) = self.fold_map.read(cx); + let (snapshot, edits) = self.tab_map.sync(snapshot, edits); + let (snapshot, edits) = self + .wrap_map + .update(cx, |map, cx| map.sync(snapshot, edits, cx)); + let mut block_map = self.block_map.write(snapshot, edits, cx); + block_map.insert(blocks, cx) + } + + pub fn remove_blocks(&mut self, ids: HashSet, cx: &mut ModelContext) { + let (snapshot, edits) = self.fold_map.read(cx); + let (snapshot, edits) = self.tab_map.sync(snapshot, edits); + let (snapshot, edits) = self + .wrap_map + .update(cx, |map, cx| map.sync(snapshot, edits, cx)); + let mut block_map = self.block_map.write(snapshot, edits, cx); + block_map.remove(ids, cx); + } + pub fn set_font(&self, font_id: FontId, font_size: f32, cx: &mut ModelContext) { self.wrap_map .update(cx, |map, cx| map.set_font(font_id, font_size, cx)); @@ -115,6 +152,7 @@ pub struct DisplayMapSnapshot { folds_snapshot: fold_map::Snapshot, tabs_snapshot: tab_map::Snapshot, wraps_snapshot: wrap_map::Snapshot, + blocks_snapshot: block_map::BlockSnapshot, } impl DisplayMapSnapshot { @@ -162,7 +200,7 @@ impl DisplayMapSnapshot { } pub fn max_point(&self) -> DisplayPoint { - DisplayPoint(self.wraps_snapshot.max_point()) + DisplayPoint(self.blocks_snapshot.max_point()) } pub fn chunks_at(&self, display_row: u32) -> wrap_map::Chunks { @@ -172,8 +210,8 @@ impl DisplayMapSnapshot { pub fn highlighted_chunks_for_rows( &mut self, display_rows: Range, - ) -> wrap_map::HighlightedChunks { - self.wraps_snapshot + ) -> block_map::HighlightedChunks { + self.blocks_snapshot .highlighted_chunks_for_rows(display_rows) } @@ -217,7 +255,7 @@ impl DisplayMapSnapshot { } pub fn clip_point(&self, point: DisplayPoint, bias: Bias) -> DisplayPoint { - DisplayPoint(self.wraps_snapshot.clip_point(point.0, bias)) + DisplayPoint(self.blocks_snapshot.clip_point(point.0, bias)) } pub fn folds_in_range<'a, T>( @@ -235,9 +273,10 @@ impl DisplayMapSnapshot { } pub fn is_line_folded(&self, display_row: u32) -> bool { - let wrap_point = DisplayPoint::new(display_row, 0).0; - let row = self.wraps_snapshot.to_tab_point(wrap_point).row(); - self.folds_snapshot.is_line_folded(row) + let block_point = BlockPoint(Point::new(display_row, 0)); + let wrap_point = self.blocks_snapshot.to_wrap_point(block_point); + let tab_point = self.wraps_snapshot.to_tab_point(wrap_point); + self.folds_snapshot.is_line_folded(tab_point.row()) } pub fn soft_wrap_indent(&self, display_row: u32) -> Option { @@ -295,11 +334,11 @@ impl DisplayMapSnapshot { } #[derive(Copy, Clone, Debug, Default, Eq, Ord, PartialOrd, PartialEq)] -pub struct DisplayPoint(wrap_map::WrapPoint); +pub struct DisplayPoint(BlockPoint); impl DisplayPoint { pub fn new(row: u32, column: u32) -> Self { - Self(wrap_map::WrapPoint::new(row, column)) + Self(BlockPoint(Point::new(row, column))) } pub fn zero() -> Self { @@ -312,29 +351,31 @@ impl DisplayPoint { } pub fn row(self) -> u32 { - self.0.row() + self.0.row } pub fn column(self) -> u32 { - self.0.column() + self.0.column } pub fn row_mut(&mut self) -> &mut u32 { - self.0.row_mut() + &mut self.0.row } pub fn column_mut(&mut self) -> &mut u32 { - self.0.column_mut() + &mut self.0.column } pub fn to_buffer_point(self, map: &DisplayMapSnapshot, bias: Bias) -> Point { - let unwrapped_point = map.wraps_snapshot.to_tab_point(self.0); + let unblocked_point = map.blocks_snapshot.to_wrap_point(self.0); + let unwrapped_point = map.wraps_snapshot.to_tab_point(unblocked_point); let unexpanded_point = map.tabs_snapshot.to_fold_point(unwrapped_point, bias).0; unexpanded_point.to_buffer_point(&map.folds_snapshot) } pub fn to_buffer_offset(self, map: &DisplayMapSnapshot, bias: Bias) -> usize { - let unwrapped_point = map.wraps_snapshot.to_tab_point(self.0); + let unblocked_point = map.blocks_snapshot.to_wrap_point(self.0); + let unwrapped_point = map.wraps_snapshot.to_tab_point(unblocked_point); let unexpanded_point = map.tabs_snapshot.to_fold_point(unwrapped_point, bias).0; unexpanded_point.to_buffer_offset(&map.folds_snapshot) } @@ -345,7 +386,8 @@ impl ToDisplayPoint for Point { let fold_point = self.to_fold_point(&map.folds_snapshot, bias); let tab_point = map.tabs_snapshot.to_tab_point(fold_point); let wrap_point = map.wraps_snapshot.to_wrap_point(tab_point); - DisplayPoint(wrap_point) + let block_point = map.blocks_snapshot.to_block_point(wrap_point); + DisplayPoint(block_point) } } diff --git a/crates/editor/src/display_map/block_map.rs b/crates/editor/src/display_map/block_map.rs index 21b41e48d1..91193c942b 100644 --- a/crates/editor/src/display_map/block_map.rs +++ b/crates/editor/src/display_map/block_map.rs @@ -16,7 +16,7 @@ use std::{ }; use sum_tree::SumTree; -struct BlockMap { +pub struct BlockMap { buffer: ModelHandle, next_block_id: AtomicUsize, wrap_snapshot: Mutex, @@ -24,18 +24,18 @@ struct BlockMap { transforms: Mutex>, } -struct BlockMapWriter<'a>(&'a mut BlockMap); +pub struct BlockMapWriter<'a>(&'a mut BlockMap); -struct BlockSnapshot { +pub struct BlockSnapshot { wrap_snapshot: WrapSnapshot, transforms: SumTree, } #[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)] -struct BlockId(usize); +pub struct BlockId(usize); #[derive(Copy, Clone, Debug, Default, Eq, Ord, PartialOrd, PartialEq)] -pub struct BlockPoint(super::Point); +pub struct BlockPoint(pub super::Point); #[derive(Debug)] struct Block { @@ -47,7 +47,7 @@ struct Block { } #[derive(Clone)] -struct BlockProperties +pub struct BlockProperties where P: Clone, T: Clone, @@ -76,7 +76,7 @@ struct TransformSummary { output_rows: u32, } -struct HighlightedChunks<'a> { +pub struct HighlightedChunks<'a> { transforms: sum_tree::Cursor<'a, Transform, (OutputRow, InputRow)>, input_chunks: wrap_map::HighlightedChunks<'a>, input_chunk: HighlightedChunk<'a>, @@ -100,7 +100,7 @@ struct InputRow(u32); struct OutputRow(u32); impl BlockMap { - fn new(buffer: ModelHandle, wrap_snapshot: WrapSnapshot) -> Self { + pub fn new(buffer: ModelHandle, wrap_snapshot: WrapSnapshot) -> Self { Self { buffer, next_block_id: AtomicUsize::new(0), @@ -113,7 +113,7 @@ impl BlockMap { } } - fn read( + pub fn read( &self, wrap_snapshot: WrapSnapshot, edits: Vec, @@ -127,7 +127,7 @@ impl BlockMap { } } - fn write( + pub fn write( &mut self, wrap_snapshot: WrapSnapshot, edits: Vec, @@ -234,21 +234,17 @@ impl BlockMap { } } -impl BlockPoint { - fn row(&self) -> u32 { - self.0.row - } +impl std::ops::Deref for BlockPoint { + type Target = Point; - fn row_mut(&mut self) -> &mut u32 { - &mut self.0.row + fn deref(&self) -> &Self::Target { + &self.0 } +} - fn column(&self) -> u32 { - self.0.column - } - - fn column_mut(&mut self) -> &mut u32 { - &mut self.0.column +impl std::ops::DerefMut for BlockPoint { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 } } @@ -308,8 +304,8 @@ impl<'a> BlockMapWriter<'a> { ids } - pub fn remove(&self, ids: HashSet) { - // + pub fn remove(&mut self, _: HashSet, _: &AppContext) { + todo!() } } @@ -347,9 +343,13 @@ impl BlockSnapshot { self.to_block_point(self.wrap_snapshot.max_point()) } + pub fn clip_point(&self, point: BlockPoint, bias: Bias) -> BlockPoint { + todo!() + } + pub fn to_block_point(&self, wrap_point: WrapPoint) -> BlockPoint { let mut cursor = self.transforms.cursor::<(InputRow, OutputRow)>(); - cursor.seek(&InputRow(wrap_point.row()), Bias::Left, &()); + cursor.seek(&InputRow(wrap_point.row()), Bias::Right, &()); while let Some(item) = cursor.item() { if item.is_isomorphic() { break; @@ -625,6 +625,10 @@ mod tests { snapshot.text(), "aaa\nBLOCK 1\nBLOCK 2\nbbb\nccc\nddd\nBLOCK 3\n" ); + assert_eq!( + snapshot.to_block_point(WrapPoint::new(1, 0)), + BlockPoint(Point::new(3, 0)) + ); // Insert a line break, separating two block decorations into separate // lines. @@ -717,13 +721,8 @@ mod tests { wrap_map.sync(tabs_snapshot, tab_edits, cx) }); let mut block_map = block_map.write(wraps_snapshot, wrap_edits, cx); - - expected_blocks.extend( - block_map - .insert(block_properties.clone(), cx) - .into_iter() - .zip(block_properties), - ); + let block_ids = block_map.insert(block_properties.clone(), cx); + expected_blocks.extend(block_ids.into_iter().zip(block_properties)); } 40..=59 => { let block_count = rng.gen_range(1..=4.min(expected_blocks.len())); @@ -740,9 +739,8 @@ mod tests { let (wraps_snapshot, wrap_edits) = wrap_map.update(cx, |wrap_map, cx| { wrap_map.sync(tabs_snapshot, tab_edits, cx) }); - let block_map = block_map.write(wraps_snapshot, wrap_edits, cx); - - block_map.remove(block_ids_to_remove); + let mut block_map = block_map.write(wraps_snapshot, wrap_edits, cx); + block_map.remove(block_ids_to_remove, cx); } _ => { buffer.update(cx, |buffer, _| buffer.randomly_edit(&mut rng, 5));