WIP: Start on `WrapMap`

Antonio Scandurra created

Change summary

zed/src/editor/display_map.rs          |   1 
zed/src/editor/display_map/fold_map.rs |   5 
zed/src/editor/display_map/wrap_map.rs | 151 +++++++++++++++++++++++++++
3 files changed, 154 insertions(+), 3 deletions(-)

Detailed changes

zed/src/editor/display_map/fold_map.rs 🔗

@@ -27,15 +27,14 @@ pub struct FoldMap {
 impl FoldMap {
     pub fn new(buffer_handle: ModelHandle<Buffer>, cx: &AppContext) -> Self {
         let buffer = buffer_handle.read(cx);
-        let text_summary = buffer.text_summary();
         Self {
             buffer: buffer_handle,
             folds: Default::default(),
             transforms: Mutex::new(SumTree::from_item(
                 Transform {
                     summary: TransformSummary {
-                        buffer: text_summary.clone(),
-                        display: text_summary,
+                        buffer: buffer.text_summary(),
+                        display: buffer.text_summary(),
                     },
                     display_text: None,
                 },

zed/src/editor/display_map/wrap_map.rs 🔗

@@ -0,0 +1,151 @@
+use crate::{
+    editor::{display_map::FoldMap, Buffer, TextSummary},
+    sum_tree::{self, SumTree},
+    time,
+};
+use gpui::{AppContext, Entity, ModelContext, ModelHandle, Task};
+use parking_lot::Mutex;
+use postage::{
+    mpsc,
+    prelude::{Sink, Stream},
+    watch,
+};
+
+#[derive(Clone)]
+struct Snapshot {
+    transforms: SumTree<Transform>,
+    version: time::Global,
+}
+
+struct State {
+    snapshot: Snapshot,
+    interpolated_version: time::Global,
+}
+
+struct WrapMap {
+    buffer: ModelHandle<Buffer>,
+    fold_map: FoldMap,
+    state: Mutex<State>,
+    background_snapshots: watch::Receiver<Snapshot>,
+    _background_task: Task<()>,
+}
+
+impl Entity for WrapMap {
+    type Event = ();
+}
+
+impl WrapMap {
+    fn new(buffer_handle: ModelHandle<Buffer>, cx: &mut ModelContext<Self>) -> Self {
+        let buffer = buffer_handle.read(cx).clone();
+        let version = buffer.version();
+        let snapshot = Snapshot {
+            transforms: SumTree::from_item(
+                Transform {
+                    summary: TransformSummary {
+                        buffer: buffer.text_summary(),
+                        display: buffer.text_summary(),
+                    },
+                    display_text: None,
+                },
+                &(),
+            ),
+            version: version.clone(),
+        };
+        let (background_snapshots_tx, background_snapshots_rx) =
+            watch::channel_with(snapshot.clone());
+        let (buffers_tx, buffers_rx) = mpsc::channel(32);
+        cx.observe(&buffer_handle, move |_, buffer, cx| {
+            let mut buffers_tx = buffers_tx.clone();
+            let buffer = buffer.read(cx).clone();
+            cx.spawn_weak(|_, _| async move {
+                let _ = buffers_tx.send(buffer).await;
+            })
+            .detach();
+        });
+        let background_task = cx.background().spawn(async move {
+            let mut wrapper = BackgroundWrapper::new(buffers_rx, background_snapshots_tx);
+            wrapper.run(buffer).await;
+        });
+
+        Self {
+            buffer: buffer_handle.clone(),
+            fold_map: FoldMap::new(buffer_handle, cx.as_ref()),
+            state: Mutex::new(State {
+                snapshot,
+                interpolated_version: version,
+            }),
+            background_snapshots: background_snapshots_rx,
+            _background_task: background_task,
+        }
+    }
+}
+
+struct BackgroundWrapper {
+    buffers_rx: mpsc::Receiver<Buffer>,
+    snapshots_tx: watch::Sender<Snapshot>,
+    snapshot: Snapshot,
+}
+
+impl BackgroundWrapper {
+    fn new(buffers_rx: mpsc::Receiver<Buffer>, snapshots_tx: watch::Sender<Snapshot>) -> Self {
+        Self {
+            buffers_rx,
+            snapshots_tx,
+            snapshot: Snapshot {
+                transforms: Default::default(),
+                version: Default::default(),
+            },
+        }
+    }
+
+    async fn run(&mut self, buffer: Buffer) {
+        if !self.sync(buffer).await {
+            return;
+        }
+
+        while let Some(buffer) = self.buffers_rx.recv().await {
+            if !self.sync(buffer).await {
+                break;
+            }
+        }
+    }
+
+    async fn sync(&mut self, buffer: Buffer) -> bool {
+        self.snapshots_tx.send(self.snapshot.clone()).await.is_ok()
+    }
+}
+
+#[derive(Clone, Debug, Default, Eq, PartialEq)]
+struct Transform {
+    summary: TransformSummary,
+    display_text: Option<&'static str>,
+}
+
+impl sum_tree::Item for Transform {
+    type Summary = TransformSummary;
+
+    fn summary(&self) -> Self::Summary {
+        self.summary.clone()
+    }
+}
+
+#[derive(Clone, Debug, Default, Eq, PartialEq)]
+struct TransformSummary {
+    display: TextSummary,
+    buffer: TextSummary,
+}
+
+impl sum_tree::Summary for TransformSummary {
+    type Context = ();
+
+    fn add_summary(&mut self, other: &Self, _: &()) {
+        self.buffer += &other.buffer;
+        self.display += &other.display;
+    }
+}
+
+impl<'a> sum_tree::Dimension<'a, TransformSummary> for TransformSummary {
+    fn add_summary(&mut self, summary: &'a TransformSummary, _: &()) {
+        sum_tree::Summary::add_summary(self, summary, &());
+    }
+}