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