Skip to main content

duat_core/buffer/
history.rs

1//! The history for a [`Text`].
2//!
3//! The [`History`] is composed of [`Moment`]s, each having a list of
4//! [`Change`]s. Whenever you [`undo`]/[`redo`], you are
5//! undoing/redoing a whole [`Moment`], with all of its [`Change`]s,
6//! all at once.
7//!
8//! This permits Vim style undoing (one [`Change`] per [`Moment`]) as
9//! well as Kakoune style undoing (multiple [`Change`]s per
10//! [`Moment`]).
11//!
12//! [`undo`]: Text::undo
13//! [`redo`]: Text::redo
14use std::{
15    iter::{Chain, Enumerate},
16    marker::PhantomData,
17    ops::Range,
18    sync::{Arc, LazyLock, Mutex},
19};
20
21use bincode::{BorrowDecode, Decode, Encode};
22use gap_buf::GapBuffer;
23
24use super::{Point, Text};
25use crate::{
26    Ranges,
27    buffer::{Buffer, BufferId, BufferOpts},
28    mode::Selections,
29    text::{Strs, Tags, TextRange},
30    utils::{add_shifts as add, merging_range_by_guess_and_lazy_shift},
31};
32
33/// The history of edits, contains all moments.
34#[derive(Debug)]
35pub struct History {
36    // Moments in regard to undoing/redoing.
37    new_moment: Moment,
38    undo_redo_moments: Vec<Moment>,
39    cur_moment: usize,
40    // Moments in regard to BufferTrackers.
41    unread_moments: Vec<UnreadMoment>,
42    // The moment where a [`Buffer`] was saved.
43    //
44    // [`Buffer`]: crate::buffer::Buffer
45    saved_moment: Option<usize>,
46}
47
48impl History {
49    /// Returns a new `History`.
50    #[allow(clippy::new_without_default)]
51    pub const fn new() -> Self {
52        Self {
53            new_moment: Moment::new(),
54            undo_redo_moments: Vec::new(),
55            cur_moment: 0,
56            unread_moments: Vec::new(),
57            saved_moment: None,
58        }
59    }
60
61    /// Adds a [`Change`] to the [`History`].
62    pub fn apply_change(
63        &mut self,
64        guess_i: Option<usize>,
65        change: Change<'static, String>,
66    ) -> usize {
67        for unread in self.unread_moments.iter_mut() {
68            unread.add_change(guess_i, change.clone());
69        }
70        self.new_moment.add_change(guess_i, change)
71    }
72
73    /// Declares that the current moment is complete and starts a
74    /// new one.
75    pub fn new_moment(&mut self) {
76        if self.new_moment.is_empty() {
77            return;
78        }
79
80        self.undo_redo_moments.truncate(self.cur_moment);
81
82        if let Some(saved_moment) = self.saved_moment
83            && saved_moment >= self.cur_moment
84        {
85            self.saved_moment = None;
86        }
87
88        self.undo_redo_moments
89            .push(std::mem::take(&mut self.new_moment));
90        self.cur_moment += 1;
91    }
92
93    /// Redoes the next [`Moment`], returning its [`Change`]s.
94    ///
95    /// Applying these [`Change`]s in the order that they're given
96    /// will result in a correct redoing.
97    pub(crate) fn move_forward(
98        &mut self,
99    ) -> Option<(impl ExactSizeIterator<Item = Change<'_>>, bool)> {
100        self.new_moment();
101        if self.cur_moment == self.undo_redo_moments.len() {
102            None
103        } else {
104            self.cur_moment += 1;
105
106            let iter = self.undo_redo_moments[self.cur_moment - 1]
107                .iter()
108                .enumerate()
109                .map(|(i, change)| {
110                    for unread in self.unread_moments.iter_mut() {
111                        unread.add_change(Some(i), change.to_string_change());
112                    }
113                    change
114                });
115
116            let is_saved = self.saved_moment.is_some_and(|m| m == self.cur_moment);
117            Some((iter, is_saved))
118        }
119    }
120
121    /// Undoes a [`Moment`], returning its reversed [`Change`]s.
122    ///
123    /// These [`Change`]s will already be shifted corectly, such that
124    /// applying them in sequential order, without further
125    /// modifications, will result in a correct undoing.
126    pub(crate) fn move_backwards(
127        &mut self,
128    ) -> Option<(impl ExactSizeIterator<Item = Change<'_>>, bool)> {
129        self.new_moment();
130        if self.cur_moment == 0 {
131            None
132        } else {
133            self.cur_moment -= 1;
134
135            let iter = self.undo_redo_moments[self.cur_moment]
136                .iter()
137                .undone()
138                .enumerate()
139                .map(|(i, change)| {
140                    for unread in self.unread_moments.iter_mut() {
141                        unread.add_change(Some(i), change.to_string_change());
142                    }
143                    change
144                });
145
146            let is_saved = self.saved_moment.is_some_and(|m| m == self.cur_moment);
147            Some((iter, is_saved))
148        }
149    }
150
151    /// Declares that the current state of the [`Text`] was saved on
152    /// disk.
153    pub(super) fn declare_saved(&mut self) {
154        self.saved_moment = Some(self.cur_moment)
155    }
156}
157
158impl Clone for History {
159    fn clone(&self) -> Self {
160        Self {
161            new_moment: self.new_moment.clone(),
162            undo_redo_moments: self.undo_redo_moments.clone(),
163            cur_moment: self.cur_moment,
164            unread_moments: Vec::new(),
165            saved_moment: self.saved_moment,
166        }
167    }
168}
169
170/// A moment in history, which may contain changes, or may just
171/// contain selections.
172///
173/// It also contains information about how to print the buffer, so
174/// that going back in time is less jarring.
175#[derive(Clone, Default, Debug)]
176pub struct Moment {
177    changes: GapBuffer<Change<'static, String>>,
178    shift_state: (usize, [i32; 3]),
179}
180
181impl Moment {
182    /// Returns a new `Moment`.
183    const fn new() -> Self {
184        Self {
185            changes: GapBuffer::new(),
186            shift_state: (0, [0; 3]),
187        }
188    }
189}
190
191impl<Context> Decode<Context> for Moment {
192    fn decode<D: bincode::de::Decoder<Context = Context>>(
193        decoder: &mut D,
194    ) -> Result<Self, bincode::error::DecodeError> {
195        Ok(Moment {
196            changes: GapBuffer::from_iter(Vec::<Change<'static, String>>::decode(decoder)?),
197            shift_state: Decode::decode(decoder)?,
198        })
199    }
200}
201
202impl Encode for Moment {
203    fn encode<E: bincode::enc::Encoder>(
204        &self,
205        encoder: &mut E,
206    ) -> Result<(), bincode::error::EncodeError> {
207        let changes = self.changes.iter().cloned().collect::<Vec<_>>();
208        changes.encode(encoder)?;
209        self.shift_state.encode(encoder)
210    }
211}
212
213impl Moment {
214    /// First try to merge this change with as many changes as
215    /// possible, then add it in.
216    pub(crate) fn add_change(
217        &mut self,
218        guess_i: Option<usize>,
219        mut change: Change<'static, String>,
220    ) -> usize {
221        let new_shift = change.shift();
222        let (from, shift) = self.shift_state;
223
224        // The range of changes that will be drained.
225        let m_range = merging_range_by_guess_and_lazy_shift(
226            (&self.changes, self.changes.len()),
227            (guess_i.unwrap_or(0), [change.start(), change.taken_end()]),
228            (from, shift, [0; 3], Point::shift_by),
229            (Change::start, Change::added_end),
230        );
231
232        // If sh_from < c_range.end, I need to shift the changes between the
233        // two, so that they match the shifting of the changes before sh_from.
234        if from < m_range.end && shift != [0; 3] {
235            for change in self.changes.range_mut(from..m_range.end).iter_mut() {
236                change.shift_by(shift);
237            }
238        // Otherwise, the shifting will happen in reverse, and `from`
239        // will be moved backwards until the point where m_range ends.
240        // This is better for localized Changes.
241        } else if from > m_range.end && shift != [0; 3] {
242            for change in self.changes.range_mut(m_range.end..from).iter_mut() {
243                change.shift_by(shift.map(|i| -i));
244            }
245        }
246
247        match m_range.len() {
248            1 => {
249                let old = std::mem::replace(&mut self.changes[m_range.start], change);
250                self.changes[m_range.start].try_merge(old);
251            }
252            _ => {
253                let changes: Vec<_> = self.changes.drain(m_range.clone()).collect();
254                for c in changes.into_iter().rev() {
255                    change.try_merge(c);
256                }
257                self.changes.insert(m_range.start, change);
258            }
259        }
260
261        if m_range.start + 1 < self.changes.len() {
262            self.shift_state = (m_range.start + 1, add(shift, new_shift));
263        } else {
264            self.shift_state = (0, [0; 3]);
265        }
266
267        m_range.start
268    }
269
270    /// An [`ExactSizeIterator`] over the [`Change`]s in this
271    /// `Moment`.
272    pub fn iter(&self) -> Changes<'_> {
273        Changes {
274            moment: self,
275            iter: self.changes.iter().enumerate(),
276            undo_shift: None,
277        }
278    }
279
280    /// Returns the number of [`Change`]s in this `Moment`
281    pub fn len(&self) -> usize {
282        self.changes.len()
283    }
284
285    /// Wether there are any [`Change`]s in this `Moment`
286    ///
287    /// This can happen when creating a [`Moment::default`].
288    #[must_use]
289    pub fn is_empty(&self) -> bool {
290        self.len() == 0
291    }
292}
293
294/// A change in a buffer, with a start, taken text, and added text
295///
296/// If you acquired this `Change` from a [`BufferTracker::parts`]
297/// call, you need not worry about adding it to the ranges that need
298/// to be updated, as that has already been done.
299#[derive(Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
300pub struct Change<'h, S = &'h str> {
301    start: [i32; 3],
302    added: S,
303    taken: S,
304    added_end: [i32; 3],
305    taken_end: [i32; 3],
306    _ghost: PhantomData<&'h str>,
307}
308
309impl Change<'static, String> {
310    /// Returns a new [Change].
311    pub fn new(edit: impl ToString, range: Range<Point>, text: &Text) -> Self {
312        let added = {
313            let edit = edit.to_string();
314            // A '\n' must be kept at the end, no matter what.
315            if (range.start == text.end_point() || range.end == text.end_point())
316                && !edit.ends_with('\n')
317            {
318                edit + "\n"
319            } else {
320                edit
321            }
322        };
323
324        let taken = text[range.clone()].to_string();
325        let added_end = add(
326            range.start.as_signed(),
327            Point::end_point_of(&added).as_signed(),
328        );
329        Change {
330            start: range.start.as_signed(),
331            added,
332            taken,
333            added_end,
334            taken_end: range.end.as_signed(),
335            _ghost: PhantomData,
336        }
337    }
338
339    /// Returns a copyable [`Change`]
340    pub fn as_ref(&self) -> Change<'_, &str> {
341        Change {
342            start: self.start,
343            added: &self.added,
344            taken: &self.taken,
345            added_end: self.added_end,
346            taken_end: self.taken_end,
347            _ghost: PhantomData,
348        }
349    }
350
351    /// In this function, it is assumed that `self` happened
352    /// _after_ `newer`
353    ///
354    /// If the merger fails, the older [`Change`] will be returned;
355    pub fn try_merge(&mut self, mut older: Self) {
356        if has_start_of(older.added_range(), self.taken_range()) {
357            let fixed_end = older.added_end().min(self.taken_end());
358
359            let start = sub(self.start, older.start);
360            let end = sub(fixed_end.as_signed(), older.start);
361            let range = start[0] as usize..end[0] as usize;
362            older.added.replace_range(range, &self.added);
363
364            let range = (fixed_end.byte() - self.start[0] as usize)..;
365
366            older.taken.push_str(&self.taken[range]);
367
368            *self = older;
369        } else if has_start_of(self.taken_range(), older.added_range()) {
370            let fixed_end = self.taken_end().min(older.added_end());
371
372            let start = sub(older.start, self.start);
373            let end = sub(fixed_end.as_signed(), self.start);
374            let range = start[0] as usize..end[0] as usize;
375            self.taken.replace_range(range, &older.taken);
376
377            let range = (fixed_end.byte() - older.start[0] as usize)..;
378
379            self.added.push_str(&older.added[range]);
380        } else {
381            panic!("Changes chosen that don't interact");
382        }
383        self.added_end = add(self.start, Point::end_point_of(&self.added).as_signed());
384        self.taken_end = add(self.start, Point::end_point_of(&self.taken).as_signed());
385    }
386}
387
388impl<'h> Change<'h> {
389    /// Creates a [`Change<String>`] from a [`Change<&str>`]
390    pub fn to_string_change(&self) -> Change<'static, String> {
391        Change {
392            start: self.start,
393            added: self.added.to_string(),
394            taken: self.taken.to_string(),
395            added_end: self.added_end,
396            taken_end: self.taken_end,
397            _ghost: PhantomData,
398        }
399    }
400
401    /// Returns a new copyable [`Change`] from an insertion.
402    pub fn str_insert(added_str: &'h str, start: Point) -> Self {
403        Self {
404            start: start.as_signed(),
405            added: added_str,
406            taken: "",
407            added_end: (start + Point::end_point_of(added_str)).as_signed(),
408            taken_end: start.as_signed(),
409            _ghost: PhantomData,
410        }
411    }
412}
413
414impl<'s, S: std::borrow::Borrow<str>> Change<'s, S> {
415    /// Returns a reversed version of this [`Change`]
416    pub fn reverse(self) -> Self {
417        Self {
418            start: self.start,
419            added: self.taken,
420            taken: self.added,
421            added_end: self.taken_end,
422            taken_end: self.added_end,
423            _ghost: PhantomData,
424        }
425    }
426
427    /// Gets a [`Range<Point>`], from the start to the end of the
428    /// affected lines
429    ///
430    /// For example, if you make an edit that transforms lines `1..=3`
431    /// to lines `1..=5`, this function will return a [`Range`] that
432    /// starts at the beginning of line 1, and ends at the end of line
433    /// 5.
434    ///
435    /// # Note
436    ///
437    /// This end of this range will come _after_ the last `\n`,
438    /// which means that, in that example, said point would have a
439    /// [`Point::line`] value equal to 6, _not_ 5, since it
440    /// represents both the end of line 5, and the beginning of line
441    /// 6.
442    #[track_caller]
443    pub fn line_range(&self, strs: &Strs) -> Range<Point> {
444        let full = strs.full();
445        let start = full.point_at_coords(self.start[2] as usize, 0);
446        if self.added_end[2] as usize == full.end_point().line() {
447            start..full.end_point()
448        } else {
449            let end_line = full.line(self.added_end[2] as usize);
450            start..end_line.range().end
451        }
452    }
453
454    /// The [`Point`] at the start of the change
455    pub fn start(&self) -> Point {
456        to_point(self.start)
457    }
458
459    /// Returns the end of the [`Change`], before it was applied
460    pub fn taken_end(&self) -> Point {
461        to_point(self.taken_end)
462    }
463
464    /// Returns the end of the [`Change`], after it was applied
465    pub fn added_end(&self) -> Point {
466        to_point(self.added_end)
467    }
468
469    /// Returns the taken [`Range`]
470    pub fn taken_range(&self) -> Range<Point> {
471        self.start()..self.taken_end()
472    }
473
474    /// Returns the added [`Range`]
475    pub fn added_range(&self) -> Range<Point> {
476        self.start()..self.added_end()
477    }
478
479    /// The text that was taken on this [`Change`]
480    pub fn added_str(&self) -> &str {
481        self.added.borrow()
482    }
483
484    /// The text that was added by this [`Change`]
485    pub fn taken_str(&self) -> &str {
486        self.taken.borrow()
487    }
488
489    /// The total shift caused by this [`Change`]
490    pub fn shift(&self) -> [i32; 3] {
491        [
492            self.added_end[0] - self.taken_end[0],
493            self.added_end[1] - self.taken_end[1],
494            self.added_end[2] - self.taken_end[2],
495        ]
496    }
497
498    /// Shifts the [`Change`] by a "signed point"
499    pub(crate) fn shift_by(&mut self, shift: [i32; 3]) {
500        self.start = add(self.start, shift);
501        self.added_end = add(self.added_end, shift);
502        self.taken_end = add(self.taken_end, shift);
503    }
504}
505
506impl<'s, S: std::fmt::Debug> std::fmt::Debug for Change<'s, S> {
507    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
508        struct DebugArray([i32; 3]);
509
510        impl std::fmt::Debug for DebugArray {
511            fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
512                write!(f, "{:?}", self.0)
513            }
514        }
515
516        f.debug_struct("Change")
517            .field("start", &DebugArray(self.start))
518            .field("added", &self.added)
519            .field("taken", &self.taken)
520            .field("added_end", &DebugArray(self.added_end))
521            .field("taken_end", &DebugArray(self.taken_end))
522            .field("_ghost", &self._ghost)
523            .finish()
524    }
525}
526
527impl Encode for Change<'static, String> {
528    fn encode<E: bincode::enc::Encoder>(
529        &self,
530        encoder: &mut E,
531    ) -> Result<(), bincode::error::EncodeError> {
532        Encode::encode(&self.start, encoder)?;
533        Encode::encode(&self.added, encoder)?;
534        Encode::encode(&self.taken, encoder)?;
535        Encode::encode(&self.added_end, encoder)?;
536        Encode::encode(&self.taken_end, encoder)?;
537        Ok(())
538    }
539}
540
541impl<Context> Decode<Context> for Change<'static, String> {
542    fn decode<D: bincode::de::Decoder<Context = Context>>(
543        decoder: &mut D,
544    ) -> Result<Self, bincode::error::DecodeError> {
545        Ok(Self {
546            start: Decode::decode(decoder)?,
547            added: Decode::decode(decoder)?,
548            taken: Decode::decode(decoder)?,
549            added_end: Decode::decode(decoder)?,
550            taken_end: Decode::decode(decoder)?,
551            _ghost: PhantomData,
552        })
553    }
554}
555
556impl<'de, Context> BorrowDecode<'de, Context> for Change<'static, String> {
557    fn borrow_decode<D: bincode::de::BorrowDecoder<'de, Context = Context>>(
558        decoder: &mut D,
559    ) -> Result<Self, bincode::error::DecodeError> {
560        Ok(Self {
561            start: Decode::decode(decoder)?,
562            added: Decode::decode(decoder)?,
563            taken: Decode::decode(decoder)?,
564            added_end: Decode::decode(decoder)?,
565            taken_end: Decode::decode(decoder)?,
566            _ghost: PhantomData,
567        })
568    }
569}
570
571/// A tracker to keep up to date on changes to [`Buffer`]s
572///
573/// This struct is capable of tracking all the [`Change`]s that happen
574/// to any `Buffer`. That happens through the
575/// [`BufferTracker::parts`] method, which gives a
576/// [`BufferParts`] struct, including the `Buffer`'s [`Strs`],
577/// [`Tags`], [`Selections`], as well as an [`ExactSizeIterator`] over
578/// the `Change`s that took place since the last call to this
579/// function, and a [`RangesToUpdate`] associated with the [`Buffer`]
580///
581/// The [`RangesToUpdate`] is a struct that keeps track of the ranges
582/// where changes have taken place, and informs you on which ones need
583/// to be updated based on what is currently visible on screen. At the
584/// start, this will include the full range of the `Buffer`, since
585/// Duat assumes that you will want to update the whole buffer.
586///
587/// This struct, alongside [`PerBuffer`], allows for a nice and
588/// standardised workflow for "parsers", which essentially update the
589/// [`Buffer`]s based on changes that took place and on what is
590/// presently visible. One example of such a parser can be seen in the
591/// `duat-treesitter` crate.
592///
593/// [`PerBuffer`]: super::PerBuffer
594pub struct BufferTracker {
595    id: LazyLock<TrackerId>,
596    tracked: Mutex<Vec<(BufferId, Arc<Mutex<Ranges>>)>>,
597}
598
599impl BufferTracker {
600    /// Returns a new `ChangesFetcher`
601    ///
602    /// This struct can be stored in a `static` variable, since this
603    /// function is `const`. You can then use the same
604    /// `ChangesFetcher` to fetch [`Change`]s from all [`Buffer`]s
605    pub const fn new() -> Self {
606        Self {
607            id: LazyLock::new(TrackerId::new),
608            tracked: Mutex::new(Vec::new()),
609        }
610    }
611
612    /// Gets the [`BufferParts`] of a [`Buffer`]
613    ///
614    /// This struct consists of the normal [`TextParts`], ([`Strs`],
615    /// [`Tags`], [`Selections`]), but it also includes an
616    /// [`Iterator`] over all the [`Change`]s that took place since
617    /// the last time this function was called by this tracker on this
618    /// `Buffer`.
619    ///
620    /// It is intended for borrowing the `Tags` mutably, whilst
621    /// reading from the `Strs`, `Selections` and the `Change`s that
622    /// took place.
623    ///
624    /// Returns [`None`] when calling this function on a [`Buffer`]
625    /// without first having called [`BufferTracker::register_buffer`]
626    /// on it.
627    ///
628    /// [`TextParts`]: crate::text::TextParts
629    /// [`Tags`]: crate::text::Tags
630    /// [`Selections`]: crate::mode::Selections
631    #[track_caller]
632    pub fn parts<'b>(&self, buf: &'b mut Buffer) -> Option<BufferParts<'b>> {
633        let mut tracked = self.tracked.lock().unwrap();
634
635        let buf_id = buf.buffer_id();
636
637        let (_, ranges) = tracked.iter_mut().find(|(id, ..)| *id == buf_id)?;
638        let unread = buf
639            .history
640            .unread_moments
641            .iter_mut()
642            .find(|unread| unread.id == *self.id)
643            .unwrap();
644
645        if unread.has_been_read {
646            unread.has_been_read = false;
647            unread.moment = Moment::new();
648        } else {
649            unread.has_been_read = true;
650            
651            let mut ranges_lock = ranges.lock().unwrap_or_else(|err| err.into_inner());
652            for change in unread.moment.iter() {
653                ranges_lock.shift_by(
654                    change.start().byte(),
655                    change.added_end().byte() as i32 - change.taken_end().byte() as i32,
656                );
657
658                let range = change.added_range();
659                ranges_lock.add(range.start.byte()..range.end.byte());
660            }
661        }
662
663        let parts = buf.text.parts();
664
665        Some(BufferParts {
666            strs: parts.strs,
667            tags: parts.tags,
668            selections: parts.selections,
669            changes: unread.moment.iter(),
670            ranges_to_update: RangesToUpdate {
671                ranges: ranges.clone(),
672                buf_len: parts.strs.len(),
673                _ghost: PhantomData,
674            },
675            opts: &buf.opts,
676        })
677    }
678
679    /// Registers a [`Buffer`] on the list of those that should be
680    /// tracked
681    ///
682    /// Does nothing if the `Buffer` was already registered.
683    pub fn register_buffer(&self, buf: &mut Buffer) {
684        let mut tracked = self.tracked.lock().unwrap();
685
686        if !tracked.iter().any(|(id, ..)| *id == buf.buffer_id()) {
687            buf.history.unread_moments.push(UnreadMoment {
688                id: *self.id,
689                moment: Moment::new(),
690                has_been_read: false,
691            });
692            let ranges = Arc::new(Mutex::new(Ranges::new(0..buf.text().len())));
693            tracked.push((buf.buffer_id(), ranges));
694        }
695    }
696}
697
698impl Default for BufferTracker {
699    fn default() -> Self {
700        Self::new()
701    }
702}
703
704/// This function is like [`TextParts`], but it includes information
705/// about [`Change`]s that took place since the last call to
706/// [`BufferTracker::parts`], as well as all the ranges of the
707/// [`Text`] that still need updating.
708///
709/// [`TextParts`]: crate::text::TextParts
710pub struct BufferParts<'b> {
711    /// The [`Strs`] of the whole [`Text`] of the [`Buffer`].
712    pub strs: &'b Strs,
713    /// The [`Tags`] of the [`Buffer`].
714    ///
715    /// This, unlike [`Strs`], allows mutation in the form of
716    /// [adding] and [removing] [`Tag`]s.
717    ///
718    /// [adding]: Tags::insert
719    /// [removing]: Tags::remove
720    /// [`Tag`]: crate::text::Tag
721    pub tags: Tags<'b>,
722    /// The [`Selections`] of the [`Buffer`].
723    pub selections: &'b Selections,
724    /// An [`ExactSizeIterator`] of all [`Change`]s that took place
725    /// since the last call to [`BufferTracker::parts`]
726    pub changes: Changes<'b>,
727    /// A list of the ranges that need to be updated.
728    ///
729    /// This should be used in conjunction with visible ranges
730    /// acquired from a [`Handle<Buffer>`], in order to update only
731    /// what is visible on screen.
732    ///
733    /// [`Handle<Buffer>`]: crate::context::Handle
734    pub ranges_to_update: RangesToUpdate<'b>,
735    /// The [`BufferOpts`] of the `Buffer` in question.
736    pub opts: &'b BufferOpts,
737}
738
739/// If `lhs` contains the start of `rhs`
740fn has_start_of(lhs: Range<Point>, rhs: Range<Point>) -> bool {
741    lhs.start <= rhs.start && rhs.start <= lhs.end
742}
743
744/// Subtracts two `i32` arrays
745fn sub(lhs: [i32; 3], rhs: [i32; 3]) -> [i32; 3] {
746    [lhs[0] - rhs[0], lhs[1] - rhs[1], lhs[2] - rhs[2]]
747}
748
749/// Converts an `[i32; 3]` to a [`Point`]
750fn to_point(signed: [i32; 3]) -> Point {
751    Point::from_raw(signed[0] as usize, signed[1] as usize, signed[2] as usize)
752}
753
754/// An [`Iterator`] over the [`Change`]s of a [`Moment`]
755#[doc(hidden)]
756#[derive(Debug, Clone)]
757pub struct Changes<'h> {
758    moment: &'h Moment,
759    iter: Enumerate<
760        Chain<
761            std::slice::Iter<'h, Change<'static, String>>,
762            std::slice::Iter<'h, Change<'static, String>>,
763        >,
764    >,
765    undo_shift: Option<[i32; 3]>,
766}
767
768impl<'h> Changes<'h> {
769    /// Converts this [`Iterator`] to one over the undone version of
770    /// the [`Change`]s
771    ///
772    /// It also resets iteration to the start, so that you aren't
773    /// iterating over "done" and "undone" versions of the `Change`s
774    /// at once.
775    ///
776    /// Normally, [`Change::taken_str`] is the `&str` that was taken
777    /// from the [`Text`] by this [`Change`]. This method assumes that
778    /// you are undoing changes, so the `Change::taken_str` will now
779    /// be the `&str` that was _added_ after the `Change`, and
780    /// [`Change::added_str`] will be the `&str` that was taken.
781    ///
782    /// This method can be useful if you want to modify a [`Strs`] in
783    /// order to check out what it used to look like.
784    pub fn undone(self) -> Self {
785        Self {
786            iter: self.moment.changes.iter().enumerate(),
787            undo_shift: Some([0; 3]),
788            ..self
789        }
790    }
791}
792
793impl<'h> Iterator for Changes<'h> {
794    type Item = Change<'h>;
795
796    fn next(&mut self) -> Option<Self::Item> {
797        let change = self.iter.next().map(|(i, change)| {
798            let (from, shift) = self.moment.shift_state;
799            let mut change = change.as_ref();
800            if i >= from {
801                change.shift_by(shift);
802            }
803            change
804        })?;
805
806        Some(if let Some(undo_shift) = self.undo_shift.as_mut() {
807            let mut change = change.reverse();
808            change.shift_by(*undo_shift);
809            *undo_shift = add(*undo_shift, change.shift());
810
811            change
812        } else {
813            change
814        })
815    }
816
817    fn size_hint(&self) -> (usize, Option<usize>) {
818        self.iter.size_hint()
819    }
820}
821
822impl<'h> ExactSizeIterator for Changes<'h> {}
823
824/// A list of [`Range<usize>`]s of byte indices in a [`Buffer`] that
825/// need to be updated
826///
827/// The recommended way to use this struct is the following:
828///
829/// - Firstly, this should all probably happen in the
830///   [`BufferUpdated`] hook, which is called right before printing to
831///   the screen.
832/// - Before calling [`BufferTracker::parts`], you should retrieve the
833///   ranges that you care about updating, either through
834///   [`Handle::full_printed_range`] or
835///   [`Handle::printed_line_ranges`]. This is to update only what is
836///   visible, conserving cpu resources.
837/// - Then, with the received ranges, you can call
838///   [`RangesToUpdate::cutoff`], [`intersecting`], or
839///   [`select_from`], in order to filter out which ranges need to be
840///   updated.
841/// - If updating the ranges was successfull, you can call
842///   [`RangesToUpdate::update_on`] or [`update_intersecting`], in
843///   order to declare those ranges as updated.
844///
845/// [`BufferUpdated`]: crate::hook::BufferUpdated
846/// [`Handle::full_printed_range`]: crate::context::Handle::full_printed_range
847/// [`Handle::printed_line_ranges`]: crate::context::Handle::printed_line_ranges
848/// [`intersecting`]: RangesToUpdate::intersecting
849/// [`select_from`]: RangesToUpdate::select_from
850/// [`update_intersecting`]: RangesToUpdate::update_intersecting
851pub struct RangesToUpdate<'b> {
852    ranges: Arc<Mutex<Ranges>>,
853    buf_len: usize,
854    _ghost: PhantomData<&'b Buffer>,
855}
856
857impl<'b> RangesToUpdate<'b> {
858    /// Adds ranges to the list of those that need updating
859    ///
860    /// Later on, when duat prints on a range that intersects with
861    /// these, you can call [`Handle::full_printed_range`] or
862    /// [`Handle::printed_line_ranges`] in order to get visible
863    /// ranges, and then call [`RangesToUpdate::cutoff`], or
864    /// [`intersecting`], or [`select_from`], in order to get the
865    /// ranges that need updating, which will include these ones that
866    /// were added by this method, as well as those relating to the
867    /// changes that took place in the [`Buffer`].
868    ///
869    /// Returns `true` if any range was added at all.
870    ///
871    /// [`Handle::full_printed_range`]: crate::context::Handle::full_printed_range
872    /// [`Handle::printed_line_ranges`]: crate::context::Handle::printed_line_ranges
873    /// [`intersecting`]: Self::intersecting
874    /// [`select_from`]: Self::select_from
875    #[track_caller]
876    pub fn add_ranges(&self, to_add: impl IntoIterator<Item = impl TextRange>) -> bool {
877        let mut ranges = self.ranges.lock().unwrap();
878        let mut has_changed = false;
879        for range in to_add {
880            has_changed |= ranges.add(range.to_range(self.buf_len));
881        }
882        has_changed
883    }
884
885    /// Declares that the ranges given by the iterator have been
886    /// updated
887    ///
888    /// The visible iterator here should come from one of the methods
889    /// on the [`Handle<Buffer>`] which returns some list of visible
890    /// ranges. These include [`Handle::full_printed_range`] or
891    /// [`Handle::printed_line_ranges`]. You can, of course, also
892    /// feed only part of these lists, or some other arbitrary
893    /// range, in order to declare those updated too.
894    ///
895    /// This function will then assume that you have successfully
896    /// updated the ranges and will cut these out of the list. This
897    /// will remove the intersections between the ranges that need to
898    /// be updated and those of the iterator.
899    ///
900    /// It will _not_ completely remove ranges that partially
901    /// intersect those of the iterator, only truncating them. If you
902    /// want that behavior, see [`update_intersecting`]
903    ///
904    /// [`Handle<Buffer>`]: crate::context::Handle
905    /// [`Handle::full_printed_range`]: crate::context::Handle::full_printed_range
906    /// [`Handle::printed_line_ranges`]: crate::context::Handle::printed_line_ranges
907    /// [`update_intersecting`]: Self::update_intersecting
908    pub fn update_on(&self, visible: impl IntoIterator<Item = impl TextRange>) -> bool {
909        let mut ranges = self.ranges.lock().unwrap();
910        let mut has_changed = false;
911        for range in visible {
912            let range = range.to_range(u32::MAX as usize);
913            has_changed |= ranges.remove_on(range).count() > 0;
914        }
915        has_changed
916    }
917
918    /// Declares that any range intersecting with any of those on the
919    /// iterator has been updated
920    ///
921    /// The visible iterator here should come from one of the methods
922    /// on the [`Handle<Buffer>`] which returns some list of visible
923    /// ranges. These include [`Handle::full_printed_range`] or
924    /// [`Handle::printed_line_ranges`]. You can, of course, also
925    /// feed only part of these lists, or some other arbitrary
926    /// range, in order to declare those updated too.
927    ///
928    /// If you want a method that only removes the intersection with
929    /// the ranges that need updating, see [`update_on`].
930    ///
931    /// [`Handle<Buffer>`]: crate::context::Handle
932    /// [`Handle::full_printed_range`]: crate::context::Handle::full_printed_range
933    /// [`Handle::printed_line_ranges`]: crate::context::Handle::printed_line_ranges
934    /// [`update_on`]: Self::update_on
935    pub fn update_intersecting(&self, visible: impl IntoIterator<Item = impl TextRange>) -> bool {
936        let mut ranges = self.ranges.lock().unwrap();
937        let mut has_changed = false;
938        for range in visible {
939            let range = range.to_range(u32::MAX as usize);
940            has_changed |= ranges.remove_intersecting(range).count() > 0;
941        }
942        has_changed
943    }
944
945    /// Returns a list of intersections between the ranges that need
946    /// updating and those from an iterator
947    ///
948    /// The visible iterator here should come from one of the methods
949    /// on the [`Handle<Buffer>`] which returns some list of visible
950    /// ranges. These include [`Handle::full_printed_range`] or
951    /// [`Handle::printed_line_ranges`]. You can, of course, also
952    /// feed only part of these lists, or some other arbitrary
953    /// range, in order to declare those updated too.
954    ///
955    /// Note that this returns only the intersecting bits. If you want
956    /// a list of all ranges that at least partially intersect, see
957    /// [`intersecting`]. If you want to do the opposite, i.e., select
958    /// all ranges from the iterator that intersect with those from
959    /// the list, see [`select_from`].
960    ///
961    /// This method is useful if you don't need update full lines,
962    /// since it will only care about the ranges that have actually
963    /// changed, which aren't full lines most of the time.
964    /// [`select_from`] is more useful for updating full lines, since
965    /// you can generate a list of printed lines from
966    /// [`Handle::printed_line_ranges`], and select from those
967    /// only the ranges that have had changes in them. This pattern is
968    /// used, for example, by `duat-treesitter`.
969    ///
970    /// [`Handle<Buffer>`]: crate::context::Handle
971    /// [`Handle::full_printed_range`]: crate::context::Handle::full_printed_range
972    /// [`Handle::printed_line_ranges`]: crate::context::Handle::printed_line_ranges
973    /// [`intersecting`]: Self::intersecting
974    /// [`select_from`]: Self::select_from
975    pub fn cutoff(&self, list: impl IntoIterator<Item = impl TextRange>) -> Vec<Range<usize>> {
976        let ranges = self.ranges.lock().unwrap();
977        list.into_iter()
978            .flat_map(|range| ranges.iter_over(range.to_range(u32::MAX as usize)))
979            .collect()
980    }
981
982    /// Returns a list of all ranges that intersect with those from an
983    /// iterator
984    ///
985    /// The visible iterator here should come from one of the methods
986    /// on the [`Handle<Buffer>`] which returns some list of visible
987    /// ranges. These include [`Handle::full_printed_range`] or
988    /// [`Handle::printed_line_ranges`]. You can, of course, also
989    /// feed only part of these lists, or some other arbitrary
990    /// range, in order to declare those updated too.
991    ///
992    /// Note that this returns the full ranges, not just the parts
993    /// that intersect. If you want a list of only the
994    /// intersections, see [`cutoff`]. If you want to select the
995    /// ranges in the iterator that intersect with those from the
996    /// list, see [`select_from`].
997    ///
998    /// [`Handle<Buffer>`]: crate::context::Handle
999    /// [`Handle::full_printed_range`]: crate::context::Handle::full_printed_range
1000    /// [`Handle::printed_line_ranges`]: crate::context::Handle::printed_line_ranges
1001    /// [`cutoff`]: Self::cutoff
1002    /// [`select_from`]: Self::select_from
1003    pub fn intersecting(
1004        &self,
1005        list: impl IntoIterator<Item = impl TextRange>,
1006    ) -> Vec<Range<usize>> {
1007        let ranges = self.ranges.lock().unwrap();
1008        let mut intersecting = Vec::new();
1009
1010        // There will almost never be more than 50 or so ranges in here, so
1011        // it's ok to be a little inefficient.
1012        // Feel free to optimize this if you wish to.
1013        for range in list {
1014            for range in ranges.iter_intersecting(range.to_range(u32::MAX as usize)) {
1015                if !intersecting.contains(&range) {
1016                    intersecting.push(range);
1017                }
1018            }
1019        }
1020
1021        intersecting.sort_unstable_by(|lhs, rhs| lhs.start.cmp(&rhs.start));
1022        intersecting
1023    }
1024
1025    /// Filters an iterator to a list of ranges that intersect with
1026    /// those that need updating
1027    ///
1028    /// The visible iterator here should come from one of the methods
1029    /// on the [`Handle<Buffer>`] which returns some list of visible
1030    /// ranges. These include [`Handle::full_printed_range`] or
1031    /// [`Handle::printed_line_ranges`]. You can, of course, also
1032    /// feed only part of these lists, or some other arbitrary
1033    /// range, in order to declare those updated too.
1034    ///
1035    /// This method is really useful if you want to update on full
1036    /// lines, but only do so if the lines have actually changed. If
1037    /// the lines have had changes, those will be in the
1038    /// [`RangesToUpdate`]. This method will check if the range of a
1039    /// line intersects with the ranges that need updating. If that is
1040    /// the case, that line will be kept in the returned [`Vec`].
1041    ///
1042    /// If you want a method that returns only the ranges that have
1043    /// actually changed, check out [`cutoff`]. If you want a method
1044    /// that that returns any range from the list that intersects with
1045    /// those of the iterator, check out [`intersecting`].
1046    ///
1047    /// [`Handle<Buffer>`]: crate::context::Handle
1048    /// [`Handle::full_printed_range`]: crate::context::Handle::full_printed_range
1049    /// [`Handle::printed_line_ranges`]: crate::context::Handle::printed_line_ranges
1050    /// [`cutoff`]: Self::cutoff
1051    /// [`intersecting`]: Self::intersecting
1052    pub fn select_from(&self, list: impl IntoIterator<Item = impl TextRange>) -> Vec<Range<usize>> {
1053        let ranges = self.ranges.lock().unwrap();
1054        // There will almost never be more than 50 or so ranges in here, so
1055        // it's ok to be a little inefficient.
1056        // Feel free to optimize this if you wish to.
1057        list.into_iter()
1058            .filter_map(|range| {
1059                let range = range.to_range(u32::MAX as usize);
1060                ranges
1061                    .iter_intersecting(range.clone())
1062                    .next()
1063                    .map(|_| range)
1064            })
1065            .collect()
1066    }
1067}
1068
1069impl<'b> std::fmt::Debug for RangesToUpdate<'b> {
1070    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1071        f.debug_struct("RangesToUpdate")
1072            .field("ranges", &*self.ranges.lock().unwrap())
1073            .field("buf_len", &self.buf_len)
1074            .finish_non_exhaustive()
1075    }
1076}
1077
1078#[derive(Default, Clone, Copy, Debug, PartialEq, Eq)]
1079struct TrackerId(usize);
1080
1081impl TrackerId {
1082    /// Returns a new [`TrackerId`]
1083    fn new() -> Self {
1084        use std::sync::atomic::{AtomicUsize, Ordering::Relaxed};
1085        static COUNT: AtomicUsize = AtomicUsize::new(0);
1086        Self(COUNT.fetch_add(1, Relaxed))
1087    }
1088}
1089
1090#[derive(Debug)]
1091struct UnreadMoment {
1092    id: TrackerId,
1093    moment: Moment,
1094    has_been_read: bool,
1095}
1096
1097impl UnreadMoment {
1098    /// Adds a [`Change`], resetting the [`Moment`] first if
1099    /// necessary.
1100    fn add_change(&mut self, guess_i: Option<usize>, change: Change<'static, String>) {
1101        if self.has_been_read {
1102            self.has_been_read = false;
1103            self.moment = Moment::new();
1104        }
1105        self.moment.add_change(guess_i, change);
1106    }
1107}