duat_core/text/
mod.rs

1//! The primary data structure in Duat
2//!
3//! This struct is responsible for all of the text that will be
4//! printed to the screen, as well as any modifications on it.
5//!
6//! The [`Text`] is a very versatile holder for characters, below is a
7//! list of some of its capabilities:
8//!
9//! - Be cheaply* edited at any point, due to its two [gap buffers].
10//! - Be [colored] in any way, at any point.
11//! - Have any arbitrary range concealed, that is, hidden from view,
12//!   but still in there.
13//! - Arbitrary [ghost text], that is, [`Text`] that shows up, but is
14//!   not actually part of the `Text`, i.e., it can be easily ignored
15//!   by external modifiers (like an LSP or tree-sitter) of the
16//!   buffer, without any special checks.
17//! - [Spacers] for even more advanced alignment (also implemented by
18//!   the [Ui]).
19//! - In the future, button ranges that can interact with the mouse.
20//!
21//! The [`Text`] struct is created in two different ways:
22//!
23//! - By calling [`Text::new`] or one of its [`From`] implementations;
24//! - By building it with the [`txt!`] macro;
25//!
26//! The first method is recommended if you want a [`Text`] that will
27//! be modified by input. This is often the case if your [`Widget`] is
28//! some sort of text box, chief of which is the [`Buffer`], which is
29//! the central `Widget` of every text editor.
30//!
31//! The second method is what should be used most of the time, as it
32//! lets you quickly create formatted [`Widget`]s/[`StatusLine`] parts
33//! in a very modular way:
34//!
35//! ```rust
36//! # duat_core::doc_duat!(duat);
37//! use duat::prelude::*;
38//!
39//! fn number_of_horses(count: usize) -> Text {
40//!     if count == 1 {
41//!         txt!("[horses.count]1[horses] horse")
42//!     } else {
43//!         txt!("[horses.count]{}[horses] horses", count)
44//!     }
45//! }
46//!
47//! fn inlined_number_of_horses(count: usize) -> Text {
48//!     txt!(
49//!         "[horses.count]{count} [horses]{}",
50//!         if count == 1 { "horse" } else { "horses" }
51//!     )
52//! }
53//! ```
54//!
55//! You can use this whenever you need to update a widget, for
56//! example, just create a new [`Text`] to printed to the screen.
57//!
58//! However, when recreating the entire [`Text`] with a [`txt!`]
59//! macro would be too expensive, you can use [`Text`] modifying
60//! functions:
61//!
62//! ```rust
63//! # duat_core::form::set_initial(duat_core::form::get_initial());
64//! # duat_core::doc_duat!(duat);
65//! use duat::prelude::*;
66//!
67//! let mut prompted = txt!("[prompt]type a key: ");
68//! let end = prompted.len();
69//! prompted.replace_range(end..end, "a")
70//! ```
71//!
72//! A general rule of thumb for "too expensive" is this: if your
73//! [`Text`] can't scroll more than a few lines, it is not too
74//! expensive to rebuild. This way of editing the [`Text`] is mostly
75//! used on the [`Buffer`] widget and other textbox-like [`Widget`]s.
76//!
77//! [Spacers]: Spacer
78//! [gap buffers]: gapbuf::GapBuffer
79//! [colored]: crate::form::Form
80//! [ghost text]: Ghost
81//! [Ui]: crate::ui::traits::RawUi
82//! [`Buffer`]: crate::buffer::Buffer
83//! [`Widget`]: crate::ui::Widget
84//! [`StatusLine`]: https://docs.rs/duat/latest/duat/widgets/struct.StatusLine.html
85//! [`Mode`]: crate::mode::Mode
86#[doc(inline)]
87pub use crate::__txt__ as txt;
88pub use crate::text::{
89    builder::{AsBuilderPart, Builder, BuilderPart},
90    bytes::{Bytes, Lines, Slices, Strs},
91    iter::{FwdIter, Item, Part, RevIter},
92    search::{Matches, RegexHaystack, RegexPattern},
93    tags::{
94        Conceal, ExtraCaret, FormTag, Ghost, GhostId, MainCaret, RawTag, Spacer, SpawnTag, Tag,
95        Tagger, Taggers, Tags, ToggleId,
96    },
97    utils::{Point, TextIndex, TextRange, TextRangeOrIndex, TwoPoints, utf8_char_width},
98};
99use crate::{
100    buffer::{Change, History},
101    context::Handle,
102    data::Pass,
103    form,
104    mode::{Selection, Selections},
105    opts::PrintOpts,
106    text::{
107        tags::{FwdTags, InnerTags, RevTags},
108        utils::implPartialEq,
109    },
110    ui::{Area, SpawnId, Widget},
111};
112
113mod builder;
114mod bytes;
115mod iter;
116mod records;
117mod search;
118mod shift_list;
119mod tags;
120mod utils;
121
122/// The text of a given [`Widget`]
123///
124/// The [`Text`] is the backbone of Duat. It is the thing responsible
125/// for everything that shows up on screen.
126///
127/// You can build a [`Text`] manually, by using [`Text::new`], or with
128/// some convenience, by using the [`txt!`] macro, making use of a
129/// [`Builder`].
130///
131/// [`Widget`]: crate::ui::Widget
132pub struct Text(Box<InnerText>);
133
134#[derive(Clone)]
135struct InnerText {
136    bytes: Bytes,
137    tags: InnerTags,
138    selections: Selections,
139    has_unsaved_changes: bool,
140}
141
142impl Text {
143    ////////// Creation and Destruction of Text
144
145    /// Returns a new empty [`Text`]
146    pub fn new() -> Self {
147        Self::from_parts(Bytes::default(), Selections::new_empty())
148    }
149
150    /// Returns a new empty [`Text`] with [`Selections`] enabled
151    pub fn with_default_main_selection() -> Self {
152        Self::from_parts(Bytes::default(), Selections::new(Selection::default()))
153    }
154
155    /// Creates a [`Text`] from [`Bytes`]
156    pub(crate) fn from_parts(mut bytes: Bytes, mut selections: Selections) -> Self {
157        if bytes.slices(..).next_back().is_none_or(|b| b != b'\n') {
158            let end = bytes.len();
159            bytes.apply_change(Change::str_insert("\n", end));
160        }
161        let tags = InnerTags::new(bytes.len().byte());
162
163        let selections = if selections.iter().any(|(sel, _)| {
164            [Some(sel.caret()), sel.anchor()]
165                .into_iter()
166                .flatten()
167                .any(|point| point >= bytes.len())
168        }) {
169            Selections::new(Selection::default())
170        } else {
171            selections.correct_all(&mut bytes);
172            selections
173        };
174
175        Self(Box::new(InnerText {
176            bytes,
177            tags,
178            selections,
179            has_unsaved_changes: false,
180        }))
181    }
182
183    /// Returns a [`Builder`] for [`Text`]
184    ///
185    /// This builder can be used to iteratively create text, by
186    /// assuming that the user wants no* [`Tag`] overlap, and that
187    /// they want to construct the [`Text`] in [`Tag`]/content pairs.
188    ///
189    /// ```rust
190    /// # duat_core::doc_duat!(duat);
191    /// use duat::prelude::*;
192    /// let mut builder = Text::builder();
193    /// ```
194    pub fn builder() -> Builder {
195        Builder::new()
196    }
197
198    ////////// Querying functions
199
200    /// Whether the [`Bytes`] and `InnerTags` are empty
201    ///
202    /// This ignores the last `'\n'` in the [`Text`], since it is
203    /// always there no matter what.
204    ///
205    /// If you only want to check for the [`Bytes`], ignoring possible
206    /// [`Ghost`]s, see [`is_empty`].
207    ///
208    /// [`is_empty`]: Bytes::is_empty
209    pub fn is_empty_empty(&self) -> bool {
210        self.0.bytes.is_empty() && self.0.tags.is_empty()
211    }
212
213    /// The inner bytes of the [`Text`]
214    ///
215    /// Note that, since [`Text`] has an implementation of
216    /// [`std::ops::Deref<Target = Bytes>`], you mostly don't need
217    /// to call this method.
218    pub fn bytes(&self) -> &Bytes {
219        &self.0.bytes
220    }
221
222    /// The parts that make up a [`Text`]
223    ///
224    /// This function is used when you want to [insert]/[remove]
225    /// [`Tag`]s (i.e., borrow the inner `InnerTags` mutably via
226    /// [`Tags`]), while still being able to read from the
227    /// [`Bytes`] and [`Selections`].
228    ///
229    /// [insert]: Tags::insert
230    /// [remove]: Tags::remove
231    /// [`&mut Bytes`]: Bytes
232    pub fn parts(&mut self) -> TextParts<'_> {
233        TextParts {
234            bytes: &self.0.bytes,
235            tags: self.0.tags.tags(),
236            selections: &self.0.selections,
237        }
238    }
239
240    /// Returns the [`TextMut`] for this `Text`
241    ///
242    /// This function is used by [`Widget::text_mut`], since that
243    /// function is not supposed to allow the user to swap the
244    /// [`Text`], which could break the history of the [`Buffer`].
245    ///
246    /// For the `Buffer` specifically, it also attaches that `Buffer`
247    /// s `History` to it, which lets one undo and redo things.
248    ///
249    /// [`Buffer`]: crate::buffer::Buffer
250    pub fn as_mut(&mut self) -> TextMut<'_> {
251        TextMut { text: self, history: None }
252    }
253
254    /// Gets the indentation level on the current line
255    pub fn indent(&self, p: Point, area: &Area, opts: PrintOpts) -> usize {
256        let range = self.line_range(p.line());
257
258        area.print_iter(self, range.start.to_two_points_after(), opts)
259            .filter_map(|(caret, item)| Some(caret).zip(item.part.as_char()))
260            .find(|(_, char)| !char.is_whitespace() || *char == '\n')
261            .map(|(caret, _)| caret.x as usize)
262            .unwrap_or(0)
263    }
264
265    ////////// Tag related query functions
266
267    /// The maximum [points] in the `at`th byte
268    ///
269    /// This point is essentially the [point] at that byte, plus the
270    /// last possible [`Point`] of any [`Ghost`]s in that
271    /// position.
272    ///
273    /// [points]: TwoPoints
274    /// [point]: Bytes::point_at_byte
275    #[inline(always)]
276    #[track_caller]
277    pub fn ghost_max_points_at(&self, b: usize) -> TwoPoints {
278        let point = self.point_at_byte(b);
279        if let Some(total_ghost) = self.0.tags.ghosts_total_at(point.byte()) {
280            TwoPoints::new(point, total_ghost)
281        } else {
282            TwoPoints::new_after_ghost(point)
283        }
284    }
285
286    /// The [points] at the end of the text
287    ///
288    /// This will essentially return the [last point] of the text,
289    /// alongside the last possible [`Point`] of any
290    /// [`Ghost`] at the end of the text.
291    ///
292    /// [points]: TwoPoints
293    /// [last point]: Bytes::len
294    pub fn len_points(&self) -> TwoPoints {
295        self.ghost_max_points_at(self.len().byte())
296    }
297
298    /// Points visually after the [`TwoPoints`]
299    ///
300    /// If the [`TwoPoints`] in question is concealed, treats the
301    /// next visible character as the first character, and returns
302    /// the points of the next visible character.
303    ///
304    /// This method is useful if you want to iterator reversibly
305    /// right after a certain point, thus including the character
306    /// of said point.
307    pub fn points_after(&self, tp: TwoPoints) -> Option<TwoPoints> {
308        self.iter_fwd(tp)
309            .filter_map(|item| item.part.as_char().map(|_| item.points()))
310            .chain([self.len_points()])
311            .nth(1)
312    }
313
314    /// The visual start of the line
315    ///
316    /// This point is defined not by where the line actually begins,
317    /// but by where the last '\n' was located. For example, if
318    /// [`Tag`]s create ghost text or omit text from multiple
319    /// different lines, this point may differ from where in the
320    /// [`Text`] the real line actually begins.
321    ///
322    /// The `skip` value is how many `\n` should be skipped before
323    /// returning.
324    pub fn visual_line_start(&self, mut points: TwoPoints, skip: usize) -> TwoPoints {
325        let mut iter = self.iter_rev(points).peekable();
326        let mut total_seen = 0;
327        while let Some(peek) = iter.peek() {
328            match peek.part {
329                Part::Char('\n') => {
330                    if total_seen == skip {
331                        return points;
332                    } else {
333                        total_seen += 1;
334                    }
335                }
336                Part::Char(_) => points = iter.next().unwrap().points(),
337                _ => drop(iter.next()),
338            }
339        }
340
341        points
342    }
343
344    /// Gets the [`Ghost`] of a given [`GhostId`]
345    pub fn get_ghost(&self, id: GhostId) -> Option<&Text> {
346        self.0.tags.get_ghost(id)
347    }
348
349    ////////// Modification functions
350
351    /// Replaces a [range] in the `Text`
352    ///
353    /// # [`TextRange`] behavior:
354    ///
355    /// If you give a single [`usize`]/[`Point`], it will be
356    /// interpreted as a range from.
357    ///
358    /// [range]: TextRange
359    pub fn replace_range(&mut self, range: impl TextRange, edit: impl ToString) {
360        let range = range.to_range(self.len().byte());
361        let (start, end) = (
362            self.point_at_byte(range.start),
363            self.point_at_byte(range.end),
364        );
365        let change = Change::new(edit, start..end, self);
366
367        self.0.bytes.bytes_state += 1;
368        self.apply_change(0, change.as_ref());
369    }
370
371    /// Merges `String`s with the body of text, given a range to
372    /// replace
373    fn apply_change(&mut self, guess_i: usize, change: Change<&str>) -> usize {
374        self.0.bytes.apply_change(change);
375        self.0.tags.transform(
376            change.start().byte()..change.taken_end().byte(),
377            change.added_end().byte(),
378        );
379
380        self.0.has_unsaved_changes = true;
381        self.0.selections.apply_change(guess_i, change)
382    }
383
384    fn without_last_nl(mut self) -> Self {
385        if let Some((_, '\n')) = { self.chars_rev(..).unwrap().next() } {
386            let change = Change::remove_last_nl(self.len());
387            self.apply_change(0, change);
388        }
389        self
390    }
391
392    /// Inserts a `Text` into this `Text`, in a specific [`Point`]
393    pub fn insert_text(&mut self, p: impl TextIndex, text: &Text) {
394        let b = p.to_byte_index().min(self.last_point().byte());
395        let cap = text.last_point().byte();
396
397        let added_str = text.0.bytes.strs(..cap).unwrap().to_string();
398        let point = self.point_at_byte(b);
399        let change = Change::str_insert(&added_str, point);
400        self.apply_change(0, change);
401
402        self.0.tags.insert_tags(point, cap, &text.0.tags);
403    }
404
405    fn apply_and_process_changes<'a>(
406        &mut self,
407        changes: impl ExactSizeIterator<Item = Change<'a, &'a str>>,
408    ) {
409        self.0.selections.clear();
410
411        let len = changes.len();
412        for (i, change) in changes.enumerate() {
413            self.apply_change(0, change);
414
415            let start = change.start().min(self.last_point());
416            let added_end = match change.added_str().chars().next_back() {
417                Some(last) => change.added_end().rev(last),
418                None => start,
419            };
420
421            let selection = Selection::new(added_end, (start != added_end).then_some(start));
422            self.0.selections.insert(i, selection, i == len - 1);
423        }
424    }
425
426    ////////// Writing functions
427
428    /// Clones the inner [`Bytes`] as a [`String`]
429    ///
430    /// This function will also cut out a final '\n' from the string.
431    // NOTE: Inherent because I don't want this to implement Display
432    #[allow(clippy::inherent_to_string)]
433    pub fn to_string(&self) -> String {
434        let [s0, s1] = self.strs(..).unwrap().to_array();
435        if !s1.is_empty() {
436            s0.to_string() + s1.strip_suffix('\n').unwrap_or(s1)
437        } else {
438            s0.strip_suffix('\n').unwrap_or(s0).to_string()
439        }
440    }
441
442    /// Writes the contents of this `Text` to a [writer]
443    ///
444    /// [writer]: std::io::Write
445    pub fn save_on(&mut self, mut writer: impl std::io::Write) -> std::io::Result<usize> {
446        self.0.has_unsaved_changes = false;
447
448        let [s0, s1] = self.0.bytes.slices(..).to_array();
449        Ok(writer.write(s0)? + writer.write(s1)?)
450    }
451
452    /// Wether or not the content has changed since the last [save]
453    ///
454    /// Returns `true` only if the actual bytes of the [`Text`] have
455    /// been changed, ignoring [`Tag`]s and all the other things,
456    /// since those are not written to the filesystem.
457    ///
458    /// [save]: Text::save_on
459    pub fn has_unsaved_changes(&self) -> bool {
460        self.0.has_unsaved_changes
461    }
462
463    ////////// Tag addition/deletion functions
464
465    /// Inserts a [`Tag`] at the given position
466    pub fn insert_tag<I, R>(&mut self, tagger: Tagger, r: I, tag: impl Tag<I, R>) -> Option<R>
467    where
468        R: Copy,
469    {
470        self.0.tags.insert(tagger, r, tag, false)
471    }
472
473    /// Like [`insert_tag`], but does it after other [`Tag`]s with the
474    /// same priority
475    ///
476    /// [`insert_tag`]: Self::insert_tag
477    pub fn insert_tag_after<I, R>(&mut self, tagger: Tagger, r: I, tag: impl Tag<I, R>) -> Option<R>
478    where
479        R: Copy,
480    {
481        self.0.tags.insert(tagger, r, tag, true)
482    }
483
484    /// Removes the [`Tag`]s of a [key] from a region
485    ///
486    /// # Caution
487    ///
488    /// While it is fine to do this on your own widgets, you should
489    /// refrain from using this function in a [`Buffer`]s [`Text`], as
490    /// it must iterate over all tags in the buffer, so if there are a
491    /// lot of other tags, this operation may be slow.
492    ///
493    /// # [`TextRange`] behavior
494    ///
495    /// If you give it a [`Point`] or [`usize`], it will be treated as
496    /// a one byte range.
497    ///
498    /// [key]: Taggers
499    /// [`Buffer`]: crate::buffer::Buffer
500    pub fn remove_tags(&mut self, taggers: impl Taggers, range: impl TextRangeOrIndex) {
501        let range = range.to_range(self.len().byte());
502        self.0.tags.remove_from(taggers, range)
503    }
504
505    /// Removes all [`Tag`]s
506    ///
507    /// Refrain from using this function on [`Buffer`]s, as there may
508    /// be other [`Tag`] providers, and you should avoid messing
509    /// with their tags.
510    ///
511    /// [`Buffer`]: crate::buffer::Buffer
512    pub fn clear_tags(&mut self) {
513        self.0.tags = InnerTags::new(self.0.bytes.len().byte());
514    }
515
516    /////////// Internal synchronization functions
517
518    /// Prepares the `Text` for reloading, to be used on [`Buffer`]s
519    ///
520    /// [`Buffer`]: crate::buffer::Buffer
521    pub(crate) fn prepare_for_reloading(&mut self) {
522        self.clear_tags();
523    }
524
525    /////////// Iterator methods
526
527    /// A forward iterator of the [chars and tags] of the [`Text`]
528    ///
529    /// [chars and tags]: Part
530    pub fn iter_fwd(&self, at: TwoPoints) -> FwdIter<'_> {
531        FwdIter::new_at(self, at)
532    }
533
534    /// A reverse iterator of the [chars and tags] of the [`Text`]
535    ///
536    /// [chars and tags]: Part
537    pub fn iter_rev(&self, at: TwoPoints) -> RevIter<'_> {
538        RevIter::new_at(self, at)
539    }
540
541    /// A forward iterator over the [`Tag`]s of the [`Text`]
542    ///
543    /// This iterator will consider some [`Tag`]s before `b`, since
544    /// their ranges may overlap with `b`
545    ///
546    /// The amount of tags to look for behind depeds on the internal
547    /// `min_len` factor. You can override by providing a lookaround,
548    /// which will tell Duat how many `Tag`s to look behind. If you
549    /// set it to `Some(0)`, lookaround will be disabled.
550    ///
551    /// # Note
552    ///
553    /// Duat works fine with [`Tag`]s in the middle of a codepoint,
554    /// but external utilizers may not, so keep that in mind.
555    pub fn tags_fwd(&self, b: usize, lookaround: Option<usize>) -> FwdTags<'_> {
556        self.0.tags.fwd_at(b, lookaround)
557    }
558
559    /// An reverse iterator over the [`Tag`]s of the [`Text`]
560    ///
561    /// This iterator will consider some `Tag`s ahead of `b`, since
562    /// their ranges may overlap with `b`.
563    ///
564    /// The amount of tags to look for ahead depeds on the internal
565    /// `min_len` factor. You can override by providing a lookaround,
566    /// which will tell Duat how many `Tag`s to look ahead. If you set
567    /// it to `Some(0)`, lookaround will be disabled.
568    ///
569    /// # Note
570    ///
571    /// Duat works fine with [`Tag`]s in the middle of a codepoint,
572    /// but external utilizers may not, so keep that in mind.
573    pub fn tags_rev(&self, b: usize, lookaround: Option<usize>) -> RevTags<'_> {
574        self.0.tags.rev_at(b, lookaround)
575    }
576
577    /// A forward [`Iterator`] over the [`RawTag`]s
578    ///
579    /// This [`Iterator`] does not take into account [`Tag`] ranges
580    /// that intersect with the starting point, unlike
581    /// [`Text::tags_fwd`]
582    pub fn raw_tags_fwd(&self, b: usize) -> impl Iterator<Item = (usize, RawTag)> {
583        self.0.tags.raw_fwd_at(b)
584    }
585
586    /// A reverse [`Iterator`] over the [`RawTag`]s
587    ///
588    /// This [`Iterator`] does not take into account [`Tag`] ranges
589    /// that intersect with the starting point, unlike
590    /// [`Text::tags_rev`]
591    pub fn raw_tags_rev(&self, b: usize) -> impl Iterator<Item = (usize, RawTag)> {
592        self.0.tags.raw_rev_at(b)
593    }
594
595    /// The [`Selections`] printed to this `Text`, if they exist
596    pub fn selections(&self) -> &Selections {
597        &self.0.selections
598    }
599
600    /// A mut reference to this `Text`'s [`Selections`] if they
601    /// exist
602    pub fn selections_mut(&mut self) -> &mut Selections {
603        &mut self.0.selections
604    }
605
606    /// Gets the main [`Selection`], if there is one
607    ///
608    /// If you want a method that doesn't return an [`Option`] (for
609    /// convenience), see [`Text::main_sel`].
610    pub fn get_main_sel(&self) -> Option<&Selection> {
611        self.0.selections.get_main()
612    }
613
614    /// Gets the main [`Selection`]
615    ///
616    /// # Panics
617    ///
618    /// This method will panic if there are no `Selection`s. If you
619    /// want a non-panicking method, see [`Text::get_main_sel`].
620    #[track_caller]
621    pub fn main_sel(&self) -> &Selection {
622        self.0.selections.main()
623    }
624
625    /// A list of all [`SpawnId`]s that belong to this `Text`
626    pub fn get_spawned_ids(&self) -> impl Iterator<Item = SpawnId> {
627        self.0.tags.get_spawned_ids()
628    }
629
630    /// A struct representing how many changes took place since the
631    /// creation of this [`Text`]
632    ///
633    /// This struct tracks all [`Change`]s and [`Tag`]
634    /// additions/removals, giving you information about wether this
635    /// `Text` has changed, when comparing this to previous
636    /// [`TextState`]s of the same `Text`.
637    pub fn text_state(&self) -> TextState {
638        let (tags_state, meta_tags_state) = self.0.tags.states();
639
640        TextState {
641            bytes_state: self.0.bytes.bytes_state,
642            tags_state,
643            meta_tags_state,
644        }
645    }
646}
647
648impl std::ops::Deref for Text {
649    type Target = Bytes;
650
651    fn deref(&self) -> &Self::Target {
652        self.bytes()
653    }
654}
655
656/// A struct that allows for [`Text`] modifications from the
657/// [`Widget::text_mut`] function
658///
659/// It is pretty much identical to `&mut Text`, the difference is that
660/// you can't reassign it to a new [`Text`]. This is done in order to
661/// prevent radical changes to the `Text` of the [`Buffer`] from the
662/// outside.
663///
664/// [`Buffer`]: crate::buffer::Buffer
665#[derive(Debug)]
666pub struct TextMut<'t> {
667    text: &'t mut Text,
668    history: Option<&'t mut History>,
669}
670
671impl<'t> TextMut<'t> {
672    /// Replaces a [range] in the `Text`
673    ///
674    /// # [`TextRange`] behavior:
675    ///
676    /// If you give a single [`usize`]/[`Point`], it will be
677    /// interpreted as a range from.
678    ///
679    /// [range]: TextRange
680    pub fn replace_range(&mut self, range: impl TextRange, edit: impl ToString) {
681        let range = range.to_range(self.len().byte());
682        let (start, end) = (
683            self.point_at_byte(range.start),
684            self.point_at_byte(range.end),
685        );
686        let change = Change::new(edit, start..end, self);
687
688        self.text.0.bytes.bytes_state += 1;
689        self.text.apply_change(0, change.as_ref());
690        self.history.as_mut().map(|h| h.apply_change(None, change));
691    }
692
693    /// Applies a [`Change`] to the `Text`
694    pub(crate) fn apply_change(
695        &mut self,
696        guess_i: Option<usize>,
697        change: Change<'static, String>,
698    ) -> (Option<usize>, usize) {
699        self.text.0.bytes.bytes_state += 1;
700        let selections_taken = self
701            .text
702            .apply_change(guess_i.unwrap_or(0), change.as_ref());
703        let history = self.history.as_mut();
704        let insertion_i = history.map(|h| h.apply_change(guess_i, change));
705        (insertion_i, selections_taken)
706    }
707
708    ////////// Functions for Tag modifications
709
710    /// The parts that make up a [`Text`]
711    ///
712    /// This function is used when you want to [insert]/[remove]
713    /// [`Tag`]s (i.e., borrow the inner `InnerTags` mutably via
714    /// [`Tags`]), while still being able to read from the
715    /// [`Bytes`] and [`Selections`].
716    ///
717    /// [insert]: Tags::insert
718    /// [remove]: Tags::remove
719    /// [`&mut Bytes`]: Bytes
720    pub fn parts(self) -> TextParts<'t> {
721        self.text.parts()
722    }
723
724    /// Inserts a [`Tag`] at the given position
725    pub fn insert_tag<I, R>(&mut self, tagger: Tagger, r: I, tag: impl Tag<I, R>) -> Option<R>
726    where
727        R: Copy,
728    {
729        self.text.insert_tag(tagger, r, tag)
730    }
731
732    /// Like [`insert_tag`], but does it after other [`Tag`]s with the
733    /// same priority
734    ///
735    /// [`insert_tag`]: Self::insert_tag
736    pub fn insert_tag_after<I, R>(&mut self, tagger: Tagger, r: I, tag: impl Tag<I, R>) -> Option<R>
737    where
738        R: Copy,
739    {
740        self.text.insert_tag_after(tagger, r, tag)
741    }
742
743    /// Removes the [`Tag`]s of a [key] from a region
744    ///
745    /// # Caution
746    ///
747    /// While it is fine to do this on your own widgets, you should
748    /// refrain from using this function in a [`Buffer`]s [`Text`], as
749    /// it must iterate over all tags in the buffer, so if there are a
750    /// lot of other tags, this operation may be slow.
751    ///
752    /// # [`TextRange`] behavior
753    ///
754    /// If you give it a [`Point`] or [`usize`], it will be treated as
755    /// a one byte range.
756    ///
757    /// [key]: Taggers
758    /// [`Buffer`]: crate::buffer::Buffer
759    pub fn remove_tags(&mut self, taggers: impl Taggers, range: impl TextRangeOrIndex) {
760        let range = range.to_range(self.len().byte());
761        self.text.remove_tags(taggers, range)
762    }
763
764    /// Removes all [`Tag`]s
765    ///
766    /// Refrain from using this function on [`Buffer`]s, as there may
767    /// be other [`Tag`] providers, and you should avoid messing
768    /// with their tags.
769    ///
770    /// [`Buffer`]: crate::buffer::Buffer
771    pub fn clear_tags(&mut self) {
772        self.text.clear_tags();
773    }
774
775    /// Updates bounds, so that [`Tag`] ranges can visibly cross the
776    /// screen
777    ///
778    /// This is used in order to allow for very long [`Tag`] ranges
779    /// (say, a [`Form`] being applied on the range `3..999`) to show
780    /// up properly without having to lookback a bazillion [`Tag`]s
781    /// which could be in the way.
782    ///
783    /// [`Form`]: crate::form::Form
784    pub(crate) fn update_bounds(&mut self) {
785        self.text.0.tags.update_bounds();
786    }
787
788    /// Functions to add  all [`Widget`]s that were spawned in this
789    /// `Text`
790    ///
791    /// This function should only be called right before printing,
792    /// where it is "known" that `Widget`s can no longer get rid of
793    /// the [`SpawnTag`]s
794    ///
795    /// [`Widget`]: crate::ui::Widget
796    pub(crate) fn get_widget_spawns(
797        &mut self,
798    ) -> Vec<Box<dyn FnOnce(&mut Pass, usize, Handle<dyn Widget>) + Send>> {
799        std::mem::take(&mut self.text.0.tags.spawn_fns.0)
800    }
801
802    ////////// History functions
803
804    /// Undoes the last moment, if there was one
805    pub fn undo(&mut self) {
806        if let Some(history) = &mut self.history
807            && let Some((changes, saved_moment)) = history.move_backwards()
808        {
809            self.text.apply_and_process_changes(changes);
810            self.text.0.bytes.bytes_state += 1;
811            self.text.0.has_unsaved_changes = !saved_moment;
812        }
813    }
814
815    /// Redoes the last moment in the history, if there is one
816    pub fn redo(&mut self) {
817        if let Some(history) = &mut self.history
818            && let Some((changes, saved_moment)) = history.move_forward()
819        {
820            self.text.apply_and_process_changes(changes);
821            self.text.0.bytes.bytes_state += 1;
822            self.text.0.has_unsaved_changes = !saved_moment;
823        }
824    }
825
826    /// Finishes the current moment and adds a new one to the history
827    pub fn new_moment(&mut self) {
828        if let Some(h) = &mut self.history {
829            h.new_moment()
830        }
831    }
832
833    /// Attaches a history to this `TextMut`
834    pub(crate) fn attach_history(&mut self, history: &'t mut History) {
835        self.history = Some(history);
836    }
837
838    ////////// Selections functions
839
840    /// A mut reference to this `Text`'s [`Selections`] if they
841    /// exist
842    pub fn selections_mut(self) -> &'t mut Selections {
843        &mut self.text.0.selections
844    }
845
846    /// Removes the tags for all the selections, used before they are
847    /// expected to move
848    pub(crate) fn add_selection_tags(&mut self, area: &Area, opts: PrintOpts) {
849        let within = (self.0.selections.len() >= 500).then(|| {
850            let start = area.start_points(self, opts);
851            let end = area.end_points(self, opts);
852            (start.real, end.real)
853        });
854
855        let mut add_selection = |selection: &Selection, bytes: &mut Bytes, is_main: bool| {
856            let (caret, selection) = selection.tag_bytes(bytes);
857
858            let key = Tagger::for_selections();
859            let form = if is_main {
860                self.text.0.tags.insert(key, caret, MainCaret, false);
861                form::M_SEL_ID
862            } else {
863                self.text.0.tags.insert(key, caret, ExtraCaret, false);
864                form::E_SEL_ID
865            };
866
867            if let Some(range) = selection {
868                self.text.0.tags.insert(key, range, form.to_tag(95), false);
869            }
870        };
871
872        if let Some((start, end)) = within {
873            for (_, selection, is_main) in self.text.0.selections.iter_within(start..end) {
874                add_selection(selection, &mut self.text.0.bytes, is_main);
875            }
876        } else {
877            for (selection, is_main) in self.text.0.selections.iter() {
878                add_selection(selection, &mut self.text.0.bytes, is_main);
879            }
880        }
881    }
882
883    /// Removes the [`Tag`]s for all [`Selection`]s
884    pub(crate) fn remove_selection_tags(&mut self) {
885        self.remove_tags(Tagger::for_selections(), ..);
886    }
887
888    /// Adds a record for the given byte index
889    pub(crate) fn add_record_for(&mut self, point: Point) {
890        let record = [point.byte(), point.char(), point.line()];
891        self.text.0.bytes.add_record(record);
892    }
893}
894
895impl<'t> std::ops::Deref for TextMut<'t> {
896    type Target = Text;
897
898    fn deref(&self) -> &Self::Target {
899        self.text
900    }
901}
902
903impl AsRef<Bytes> for Text {
904    fn as_ref(&self) -> &Bytes {
905        self.bytes()
906    }
907}
908
909/// The Parts that make up a [`Text`]
910pub struct TextParts<'a> {
911    /// The [`Bytes`] of the [`Text`]
912    pub bytes: &'a Bytes,
913    /// The [`Tags`] of the [`Text`]
914    ///
915    /// This, unlike [`Bytes`], allows mutation in the form of
916    /// [adding] and [removing] [`Tag`]s.
917    ///
918    /// [adding]: Tags::insert
919    /// [removing]: Tags::remove
920    pub tags: Tags<'a>,
921    /// The [`Selections`] of the [`Text`]
922    ///
923    /// For most [`Widget`]s, there should be no [`Selection`], since
924    /// they are just visual.
925    ///
926    /// [`Widget`]: crate::ui::Widget
927    pub selections: &'a Selections,
928}
929
930/// A representation of how many changes took place in a [`Text`]
931///
932/// The purpose of this struct is merely to be compared with
933/// previously acquired instances of itself, to just quickly check if
934/// certain properties of the `Text` have changed.
935///
936/// Note that this is a [`Text`] agnostic struct, comparing the
937/// `TextState`s from two different `Text`s is pointless.
938#[derive(Clone, Copy, Debug, PartialEq, Eq)]
939pub struct TextState {
940    bytes_state: u64,
941    tags_state: u64,
942    meta_tags_state: u64,
943}
944
945impl TextState {
946    /// Wether there have been _any_ changes to the [`Text`] since
947    /// this previous instance
948    pub fn has_changed_since(&self, other: Self) -> bool {
949        self.bytes_state > other.bytes_state
950            || self.tags_state > other.tags_state
951            || self.meta_tags_state > other.meta_tags_state
952    }
953
954    /// Wether the [`Bytes`] have changed since this previous instance
955    pub fn bytes_have_changed_since(&self, other: Self) -> bool {
956        self.bytes_state > other.bytes_state
957    }
958
959    /// Wether the [`Tags`] have changed since this previous instance
960    ///
961    /// Note that this only tracks if [`Tag`]s have been
962    /// added/removed. So if, for example, you [replace a range] where
963    /// no `Tag`s existed, this would return `false`, even though the
964    /// position of `Tag`s have changed internally.
965    ///
966    /// [replace a range]: Text::replace_range
967    pub fn tags_have_changed_since(&self, other: Self) -> bool {
968        self.tags_state > other.tags_state
969    }
970
971    /// Wether this [`Text`] has "structurally changed" since this
972    /// previous instance
973    ///
974    /// A `Text` has structurally changed when printing it from the
975    /// same point could result in a different characters being
976    /// printed. This not only happens when the [`Bytes`] change, but
977    /// also with certain [`Tag`]s, like [`Ghost`] and [`Conceal`],
978    /// which also add and remove characters to be printed.
979    ///
980    /// These `Tag`s are called "meta tags" internally, since they
981    /// change the very structure of what `Text` has been printed.
982    pub fn has_structurally_changed_since(&self, other: Self) -> bool {
983        self.bytes_state > other.bytes_state || self.meta_tags_state > other.meta_tags_state
984    }
985}
986
987////////// Standard impls
988
989impl Default for Text {
990    fn default() -> Self {
991        Self::new()
992    }
993}
994
995impl<T: Into<Bytes>> From<T> for Text {
996    fn from(value: T) -> Self {
997        Self::from_parts(value.into(), Selections::new_empty())
998    }
999}
1000
1001impl std::fmt::Debug for Text {
1002    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1003        f.debug_struct("Text")
1004            .field("bytes", &self.0.bytes)
1005            .field("tags", &self.0.tags)
1006            .finish_non_exhaustive()
1007    }
1008}
1009
1010impl Clone for Text {
1011    fn clone(&self) -> Self {
1012        let mut text = Self(self.0.clone());
1013        if text.slices(..).next_back().is_none_or(|b| b != b'\n') {
1014            let end = text.len();
1015            text.apply_change(0, Change::str_insert("\n", end));
1016        }
1017
1018        text
1019    }
1020}
1021
1022impl Eq for Text {}
1023implPartialEq!(text: Text, other: Text,
1024    text.0.bytes == other.0.bytes && text.0.tags == other.0.tags
1025);
1026implPartialEq!(text: Text, other: &str, text.0.bytes == *other);
1027implPartialEq!(text: Text, other: String, text.0.bytes == *other);
1028implPartialEq!(str: &str, text: Text, text.0.bytes == **str);
1029implPartialEq!(str: String, text: Text, text.0.bytes == **str);
1030
1031impl Eq for TextMut<'_> {}
1032implPartialEq!(text_mut: TextMut<'_>, other: TextMut<'_>, text_mut.text == other.text);
1033implPartialEq!(text_mut: TextMut<'_>, other: Text, text_mut.text == other);
1034implPartialEq!(text_mut: TextMut<'_>, other: &str, text_mut.text.0.bytes == *other);
1035implPartialEq!(text_mut: TextMut<'_>, other: String, text_mut.text.0.bytes == *other);
1036implPartialEq!(text: Text, other: TextMut<'_>, *text == other.text);
1037implPartialEq!(str: &str, text_mut: TextMut<'_>, text_mut.text.0.bytes == **str);
1038implPartialEq!(str: String, text_mut: TextMut<'_>, text_mut.text.0.bytes == **str);