WIP

Nathan Sobo created

Change summary

zed/src/editor/display_map/wrap_map.rs | 91 ++++++++++++++++++---------
1 file changed, 59 insertions(+), 32 deletions(-)

Detailed changes

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

@@ -2,12 +2,12 @@ use super::tab_map::{
     self, Edit as InputEdit, OutputPoint as InputPoint, Snapshot as InputSnapshot, TextSummary,
 };
 use crate::{
-    editor::Point,
+    editor::{Editor, Point},
     sum_tree::{self, Cursor, SumTree},
     util::Bias,
     Settings,
 };
-use gpui::{AppContext, FontCache, FontSystem, Task};
+use gpui::{AppContext, FontCache, FontSystem, Task, ViewContext};
 use parking_lot::Mutex;
 use postage::{
     prelude::{Sink, Stream},
@@ -212,7 +212,7 @@ struct State {
 
 pub struct WrapMap {
     state: Mutex<State>,
-    edits_tx: channel::Sender<(InputSnapshot, Vec<InputEdit>)>,
+    background_changes_tx: channel::Sender<Change>,
     background_snapshot: watch::Receiver<Snapshot>,
     _background_task: Task<()>,
 }
@@ -222,7 +222,7 @@ impl WrapMap {
         input: InputSnapshot,
         settings: Settings,
         wrap_width: Option<f32>,
-        cx: &AppContext,
+        cx: &mut ViewContext<Editor>,
     ) -> Self {
         let font_cache = cx.font_cache().clone();
         let font_system = cx.platform().fonts();
@@ -244,36 +244,46 @@ impl WrapMap {
                 snapshot,
                 pending_edits: VecDeque::new(),
             }),
-            edits_tx,
+            background_changes_tx: edits_tx,
             background_snapshot: background_snapshot_rx,
             _background_task: background_task,
         }
     }
 
     pub fn sync(&self, input: InputSnapshot, edits: Vec<InputEdit>, cx: &AppContext) -> Snapshot {
-        self.edits_tx
-            .try_send((input.clone(), edits.clone()))
-            .unwrap();
-
-        let mut snapshot = self.state.lock().snapshot.clone();
         let mut background_snapshot = self.background_snapshot.clone();
-        cx.background().block_on(Duration::from_millis(5), async {
-            loop {
-                snapshot = background_snapshot.recv().await.unwrap();
-                if snapshot.input.version() == input.version() {
-                    break;
+        let mut snapshot = self.background_snapshot.borrow().clone();
+
+        if !edits.is_empty() {
+            self.background_changes_tx
+                .try_send(Change::Input {
+                    snapshot: input.clone(),
+                    edits: edits.clone(),
+                })
+                .unwrap();
+
+            cx.background().block_on(Duration::from_millis(5), async {
+                loop {
+                    snapshot = background_snapshot.recv().await.unwrap();
+                    if snapshot.input.version() == input.version() {
+                        break;
+                    }
                 }
-            }
-        });
+            });
+        }
 
         let mut state = &mut *self.state.lock();
         state.snapshot = snapshot;
         state.pending_edits.push_back((input, edits));
-        while state.pending_edits.front().map_or(false, |(input, _)| {
-            input.version() <= state.snapshot.input.version()
-        }) {
-            state.pending_edits.pop_front();
+
+        while let Some((pending_input, _)) = state.pending_edits.front() {
+            if pending_input.version() <= state.snapshot.input.version() {
+                state.pending_edits.pop_front();
+            } else {
+                break;
+            }
         }
+
         for (input, edits) in &state.pending_edits {
             state.snapshot.interpolate(input.clone(), &edits);
         }
@@ -281,7 +291,9 @@ impl WrapMap {
     }
 
     pub fn set_wrap_width(&self, width: Option<f32>) {
-        todo!()
+        self.background_changes_tx
+            .try_send(Change::Width(width))
+            .unwrap();
     }
 }
 
@@ -293,12 +305,12 @@ struct BackgroundWrapper {
     snapshot: Snapshot,
 }
 
-enum WrapChange {
-    InputChange {
+enum Change {
+    Input {
         snapshot: InputSnapshot,
         edits: Vec<tab_map::Edit>,
     },
-    WidthChange(Option<f32>),
+    Width(Option<f32>),
 }
 
 impl BackgroundWrapper {
@@ -320,21 +332,36 @@ impl BackgroundWrapper {
 
     async fn run(
         &mut self,
-        snapshot: InputSnapshot,
-        edits_rx: channel::Receiver<WrapChange>,
+        input: InputSnapshot,
+        edits_rx: channel::Receiver<Change>,
         mut snapshot_tx: watch::Sender<Snapshot>,
     ) {
         let edit = InputEdit {
-            old_lines: Default::default()..snapshot.max_point(),
-            new_lines: Default::default()..snapshot.max_point(),
+            old_lines: Default::default()..input.max_point(),
+            new_lines: Default::default()..input.max_point(),
         };
-        self.sync(snapshot, vec![edit]);
+        self.sync(input, vec![edit]);
         if snapshot_tx.send(self.snapshot.clone()).await.is_err() {
             return;
         }
 
-        while let Ok((snapshot, edits)) = edits_rx.recv().await {
-            self.sync(snapshot, edits);
+        while let Ok(change) = edits_rx.recv().await {
+            match change {
+                Change::Input { snapshot, edits } => self.sync(snapshot, edits),
+                Change::Width(wrap_width) => {
+                    if self.wrap_width == wrap_width {
+                        continue;
+                    } else {
+                        self.wrap_width = wrap_width;
+                        let input = self.snapshot.input.clone();
+                        let edit = InputEdit {
+                            old_lines: Default::default()..input.max_point(),
+                            new_lines: Default::default()..input.max_point(),
+                        };
+                        self.sync(input, vec![edit])
+                    }
+                }
+            };
             if snapshot_tx.send(self.snapshot.clone()).await.is_err() {
                 break;
             }