wip - wiring up blockmap into displaymap

Max Brunsfeld created

Change summary

crates/editor/src/display_map.rs           | 82 ++++++++++++++++++-----
crates/editor/src/display_map/block_map.rs | 68 +++++++++----------
2 files changed, 95 insertions(+), 55 deletions(-)

Detailed changes

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<WrapMap>,
+    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<Self>) -> 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<P, T>(
+        &mut self,
+        blocks: impl IntoIterator<Item = BlockProperties<P, T>>,
+        cx: &mut ModelContext<Self>,
+    ) -> Vec<BlockId>
+    where
+        P: ToOffset + Clone,
+        T: Into<Rope> + 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<BlockId>, cx: &mut ModelContext<Self>) {
+        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>) {
         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<u32>,
-    ) -> 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<u32> {
@@ -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)
     }
 }
 

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<Buffer>,
     next_block_id: AtomicUsize,
     wrap_snapshot: Mutex<WrapSnapshot>,
@@ -24,18 +24,18 @@ struct BlockMap {
     transforms: Mutex<SumTree<Transform>>,
 }
 
-struct BlockMapWriter<'a>(&'a mut BlockMap);
+pub struct BlockMapWriter<'a>(&'a mut BlockMap);
 
-struct BlockSnapshot {
+pub struct BlockSnapshot {
     wrap_snapshot: WrapSnapshot,
     transforms: SumTree<Transform>,
 }
 
 #[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<P, T>
+pub struct BlockProperties<P, T>
 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<Buffer>, wrap_snapshot: WrapSnapshot) -> Self {
+    pub fn new(buffer: ModelHandle<Buffer>, 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<WrapEdit>,
@@ -127,7 +127,7 @@ impl BlockMap {
         }
     }
 
-    fn write(
+    pub fn write(
         &mut self,
         wrap_snapshot: WrapSnapshot,
         edits: Vec<WrapEdit>,
@@ -234,21 +234,17 @@ impl BlockMap {
     }
 }
 
-impl BlockPoint {
-    fn row(&self) -> u32 {
-        self.0.row
-    }
-
-    fn row_mut(&mut self) -> &mut u32 {
-        &mut self.0.row
-    }
+impl std::ops::Deref for BlockPoint {
+    type Target = Point;
 
-    fn column(&self) -> u32 {
-        self.0.column
+    fn deref(&self) -> &Self::Target {
+        &self.0
     }
+}
 
-    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<BlockId>) {
-        //
+    pub fn remove(&mut self, _: HashSet<BlockId>, _: &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));