wrap_map.rs

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