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