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}