wrap_map.rs

  1use crate::{
  2    editor::{display_map::FoldMap, Buffer, TextSummary},
  3    sum_tree::{self, SumTree},
  4    time,
  5};
  6use gpui::{AppContext, Entity, ModelContext, ModelHandle, Task};
  7use parking_lot::Mutex;
  8use postage::{
  9    mpsc,
 10    prelude::{Sink, Stream},
 11    watch,
 12};
 13
 14#[derive(Clone)]
 15struct Snapshot {
 16    transforms: SumTree<Transform>,
 17    version: time::Global,
 18}
 19
 20struct State {
 21    snapshot: Snapshot,
 22    interpolated_version: time::Global,
 23}
 24
 25struct WrapMap {
 26    buffer: ModelHandle<Buffer>,
 27    fold_map: FoldMap,
 28    state: Mutex<State>,
 29    background_snapshots: watch::Receiver<Snapshot>,
 30    _background_task: Task<()>,
 31}
 32
 33impl Entity for WrapMap {
 34    type Event = ();
 35}
 36
 37impl WrapMap {
 38    fn new(buffer_handle: ModelHandle<Buffer>, cx: &mut ModelContext<Self>) -> Self {
 39        let buffer = buffer_handle.read(cx).clone();
 40        let version = buffer.version();
 41        let snapshot = Snapshot {
 42            transforms: SumTree::from_item(
 43                Transform {
 44                    summary: TransformSummary {
 45                        buffer: buffer.text_summary(),
 46                        display: buffer.text_summary(),
 47                    },
 48                    display_text: None,
 49                },
 50                &(),
 51            ),
 52            version: version.clone(),
 53        };
 54        let (background_snapshots_tx, background_snapshots_rx) =
 55            watch::channel_with(snapshot.clone());
 56        let (buffers_tx, buffers_rx) = mpsc::channel(32);
 57        cx.observe(&buffer_handle, move |_, buffer, cx| {
 58            let mut buffers_tx = buffers_tx.clone();
 59            let buffer = buffer.read(cx).clone();
 60            cx.spawn_weak(|_, _| async move {
 61                let _ = buffers_tx.send(buffer).await;
 62            })
 63            .detach();
 64        });
 65        let background_task = cx.background().spawn(async move {
 66            let mut wrapper = BackgroundWrapper::new(buffers_rx, background_snapshots_tx);
 67            wrapper.run(buffer).await;
 68        });
 69
 70        Self {
 71            buffer: buffer_handle.clone(),
 72            fold_map: FoldMap::new(buffer_handle, cx.as_ref()),
 73            state: Mutex::new(State {
 74                snapshot,
 75                interpolated_version: version,
 76            }),
 77            background_snapshots: background_snapshots_rx,
 78            _background_task: background_task,
 79        }
 80    }
 81}
 82
 83struct BackgroundWrapper {
 84    buffers_rx: mpsc::Receiver<Buffer>,
 85    snapshots_tx: watch::Sender<Snapshot>,
 86    snapshot: Snapshot,
 87}
 88
 89impl BackgroundWrapper {
 90    fn new(buffers_rx: mpsc::Receiver<Buffer>, snapshots_tx: watch::Sender<Snapshot>) -> Self {
 91        Self {
 92            buffers_rx,
 93            snapshots_tx,
 94            snapshot: Snapshot {
 95                transforms: Default::default(),
 96                version: Default::default(),
 97            },
 98        }
 99    }
100
101    async fn run(&mut self, buffer: Buffer) {
102        if !self.sync(buffer).await {
103            return;
104        }
105
106        while let Some(buffer) = self.buffers_rx.recv().await {
107            if !self.sync(buffer).await {
108                break;
109            }
110        }
111    }
112
113    async fn sync(&mut self, buffer: Buffer) -> bool {
114        self.snapshots_tx.send(self.snapshot.clone()).await.is_ok()
115    }
116}
117
118#[derive(Clone, Debug, Default, Eq, PartialEq)]
119struct Transform {
120    summary: TransformSummary,
121    display_text: Option<&'static str>,
122}
123
124impl sum_tree::Item for Transform {
125    type Summary = TransformSummary;
126
127    fn summary(&self) -> Self::Summary {
128        self.summary.clone()
129    }
130}
131
132#[derive(Clone, Debug, Default, Eq, PartialEq)]
133struct TransformSummary {
134    display: TextSummary,
135    buffer: TextSummary,
136}
137
138impl sum_tree::Summary for TransformSummary {
139    type Context = ();
140
141    fn add_summary(&mut self, other: &Self, _: &()) {
142        self.buffer += &other.buffer;
143        self.display += &other.display;
144    }
145}
146
147impl<'a> sum_tree::Dimension<'a, TransformSummary> for TransformSummary {
148    fn add_summary(&mut self, summary: &'a TransformSummary, _: &()) {
149        sum_tree::Summary::add_summary(self, summary, &());
150    }
151}