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}