duat_core/buffer/
parser.rs

1//! Struct that can react to change in the [`Text`]
2//!
3//! These structs will be informed of every [`Change`] that happens in
4//! the `Text`, and are allowed to act accordingly. This action will
5//! be done by telling the `Text` what parts need to be updated.
6//! They will then be updated when deemed relevant by the [Ui] in
7//! use (usually when these become visible).
8//!
9//! [Ui]: crate::ui::traits::RawUi
10//! [`Change`]: crate::text::Change
11use std::{
12    any::TypeId,
13    cell::RefCell,
14    ops::Range,
15    sync::{
16        Arc,
17        atomic::{AtomicBool, Ordering},
18    },
19};
20
21use parking_lot::Mutex;
22
23use super::Buffer;
24use crate::{
25    context::Handle,
26    data::Pass,
27    opts::PrintOpts,
28    ranges::Ranges,
29    text::{Bytes, Change, Moment, MomentFetcher, Point, Text, TextRange, txt},
30};
31
32/// A [`Buffer`] parser, that can keep up with every [`Change`] that
33/// took place
34///
35/// A parser's purpose is generally to look out for changes to the
36/// `Buffer`'s [`Bytes`], and update some internal state that
37/// represents them. Examples of things that should be implemented as
38/// `Parser`s are:
39///
40/// - A tree-sitter parser, or other syntax tree representations;
41/// - Regex parsers;
42/// - Language server protocols;
43///
44/// But `Parser`s don't have to necessarily do "big and complex"
45/// things like creating a language tree, they can be more simple,
46/// by, for example, acting on each [`Selection`] on the screen.
47///
48/// If you want a walkthrough on how to make a `Parser`, I would
49/// recommend reading the book (TODO). The rest of the documentation
50/// here is mostly just describing a final implementation, not
51/// walking through its creation.
52///
53/// # What a parser does
54///
55/// The gist of it is that a `Parser` will be called to read the
56/// `Bytes` of the `Buffer` as well as any [`Change`]s that are done
57/// to said `Buffer`. Duat will then call upon the `Parser` to "act"
58/// on a region of the `Buffer`'s [`Text`], this region being
59/// determined by what is shown on screen, in order to help plugin
60/// writers minimize the work done.
61///
62/// When creating a `Parser`, you will also be given a
63/// [`BufferTracker`]. It will be used to keep track of the
64/// [`Change`]s, and it is also used by the `Parser` to tell which
65/// [`Range<usize>`]s of the [`Text`] the `Parser` cares about. So,
66/// for example, if you're matching non-multiline regex patterns, for
67/// every `Change`, you might want to add the lines of that `Change`
68/// to the `BufferTracker`, and when Duat decides which ranges need to
69/// be updated, it will inform you: "Hey, you asked for this range to
70/// be updated, it's on screen now, so update it.".
71///
72/// # The functions from the `Parser` trait
73///
74/// There are 4 functions that you need to care about, but you may
75/// choose to implement only some of them:
76///
77/// ## [`Parser::parse`]
78///
79/// This function's purpose is for the `Parser` to update its internal
80/// state after [`Change`]s take place. Here's the _general_ layout
81/// for a _synchronous_ version of this function:
82///
83/// ```rust
84/// # duat_core::doc_duat!(duat);
85/// use duat::prelude::*;
86///
87/// struct CharCounter {
88///     count: usize,
89///     ch: char,
90///     tracker: BufferTracker,
91/// }
92///
93/// impl Parser for CharCounter {
94///     fn parse(&mut self) -> bool {
95///         // Fetches the latest Changes and Bytes of the Buffer
96///         self.tracker.update();
97///
98///         // A Moment is a list of Changes
99///         // For the sake of efficiency, Changes are sent in bulk,
100///         // rather than individually
101///         for change in self.tracker.moment().changes() {
102///             let bef_count = change.taken_str().matches(self.ch).count();
103///             let aft_count = change.taken_str().matches(self.ch).count();
104///             self.count += aft_count - bef_count;
105///         }
106///
107///         // Return true if you want to call `Parser::update`, for
108///         // this Parser, since we never change the Buffer, it's fine
109///         // to always return false.
110///         false
111///     }
112/// }
113/// ```
114///
115/// The example above just keeps track of every occurance of a
116/// specific `char`. Every time the `Buffer` is updated, the `parse`
117/// function will be called, and you can use [`BufferTracker::update`]
118/// to be notified of _every_ `Change` that takes place in the
119/// `Buffer`.
120///
121/// ## [`Parser::update`]
122///
123/// The purpose of this funcion is for the `Parser` to modify the
124/// `Buffer` itself. In the previous funcion, you may notice that you
125/// are not given access to the `Buffer` directly, nor are you given a
126/// [`Pass`] in order to access global state. That's what this
127/// function is for.
128///
129/// Below is the rough layout for an implementation of this function,
130/// in this case, this function "resets its modifications" every time
131/// it is called:
132///
133/// ```rust
134/// # duat_core::doc_duat!(duat);
135/// use duat::prelude::*;
136///
137/// struct HighlightMatch {
138///     tagger: Tagger,
139/// }
140///
141/// impl Parser for HighlightMatch {
142///     fn update(&mut self, pa: &mut Pass, handle: &Handle, on: Vec<Range<Point>>) {
143///         // Remove all tags previously added by this Parser.
144///         handle.text_mut(pa).remove_tags(self.tagger, ..);
145///
146///         // The suffix of the main cursor's current word.
147///         let Some(range) = handle.edit_main(pa, |c| c.search_fwd(r"\A\w+").next()) else {
148///             return;
149///         };
150///         // The prefix of said cursor's word.
151///         let start = handle
152///             .edit_main(pa, |c| c.search_rev(r"\w*\z").next())
153///             .map(|range| range.start)
154///             .unwrap_or(range.start);
155///
156///         // The TextParts struct lets you read from the Bytes while writing to the Tags.
157///         let mut parts = handle.text_parts(pa);
158///         let pat = parts.bytes.strs(start..range.end);
159///         let form_id = form::id_of!("same_word");
160///
161///         // Highlight every identical word.
162///         for range in on {
163///             for range in parts.bytes.search_fwd(r"\w+", range.clone()).unwrap() {
164///                 if parts.bytes.strs(range.clone()) == pat {
165///                     parts.tags.insert(self.tagger, range, form_id.to_tag(50));
166///                 }
167///             }
168///         }
169///     }
170/// }
171/// ```
172///
173/// The `Parser` above reads the word under the main cursor (if there
174/// is one) and highlights every ocurrence of said word _on screen_.
175/// This function would be called if [`Parser::parse`] returns `true`,
176/// i.e. when the `Parser` is "ready" to update the `Buffer`. The
177/// default implementation of `Parser::parse` is to just return
178/// `true`.
179///
180/// # Note
181///
182/// In the example above, the [`BufferTracker`] is acting _slightly_
183/// differently. When setting up this `Parser`, I called
184/// [`BufferTracker::track_area`].
185///
186/// This function makes it so, instead of tracking changed
187/// [`Range<Point>`]s, [`Parser::update`] will always return a list of
188/// ranges equivalent to the printed region of the [`Text`]. This way,
189/// I can update only the stuff on screen.
190///
191/// In general, given the [`Parser::parse`] and `Parser::update`
192/// functions, you can roughly divide which ones you'll implement
193/// based on the following criteria:
194///
195/// - If your `Parser` does not update the `Buffer`, and just keeps
196///   track of [`Change`]s, e.g. a word counter, or a filetype
197///   checker, etc, then you should only have to implement the
198///   [`Parser::parse`] function.
199/// - If your `Parser` actively updates the `Buffer` every time it is
200///   printed, e.g. the word match finder above, or a current line
201///   highlighter, then you should only have to implement the
202///   [`Parser::update`] function.
203/// - If, in order to update the [`Buffer`], you need to keep track of
204///   some current state, and you may even update the `Parser`'s state
205///   in other threads, like a treesitter parser for example, then you
206///   should implement both.
207///
208/// ## [`Parser::before_get`] and [`Parser::before_try_get`]
209///
210/// These functions have the same purpose as [`Parser::parse`], but
211/// they are called before calls to [`Buffer::read_parser`],
212/// [`Buffer::write_parser`], and their [try equivalents].
213///
214/// They serve to kind of "prepare" the `Parser` for functions that
215/// access it, much like [`Parser::parse`] "prepares" the `Parser` for
216/// a call to [`Parser::update`].
217///
218/// The purpose of these functions is to only ever update the `Parser`
219/// when that is actually necessary. The most notable example of this
220/// is the [`duat-jump-list`] crate. That crate defines a `Parser`
221/// that only ever updates its internal state when it is accessed
222/// externally. The reason for that is because it is only used to
223/// store and retrieve previous versions of the [`Selections`] of the
224/// [`Buffer`], so it doesn't need to update itself _every time_ there
225/// are new changes to the [`Buffer`], but only when it is requested.
226///
227/// # Note
228///
229/// You can keep a `Parser` private in your plugin in order to
230/// prevent the end user from reading or writing to it. You can
231/// then create standalone functions or implement traits on the
232/// [`Buffer`] widget in order to give controled access to the
233/// parser. For an example of this, you can see the
234/// [`duat-jump-list`] crate, which defines traits for saving and
235/// retrieving jumps, but doesn't grant direct access to the parser.
236///
237/// [`Change`]: crate::text::Change
238/// [`Selection`]: crate::mode::Selection
239/// [try equivalents]: Buffer::try_read_parser
240/// [`duat-jump-list`]: https://github.com/AhoyISki/duat-jump-list
241/// [`Selections`]: crate::mode::Selections
242#[allow(unused_variables)]
243pub trait Parser: Send + 'static {
244    /// Parses the [`Bytes`] of the [`Buffer`]
245    ///
246    /// This function is called every time the [`Buffer`] is updated,
247    /// and it's where you should update the internal state of the
248    /// [`Parser`] to reflect any [`Change`]s that took place.
249    ///
250    /// [`Tag`]: crate::text::Tag
251    /// [`Change`]: crate::text::Change
252    /// [`Buffer`]: crate::buffer::Buffer
253    /// [add]: Ranges::add
254    /// [remove]: Ranges::remove
255    /// [`update`]: Parser::update
256    fn parse(&mut self) -> bool {
257        true
258    }
259
260    /// Updates the [`Buffer`] in some given [`Range<Point>`]s
261    ///
262    /// As this function is called, the state of the [`Parser`] needs
263    /// to already be synced up with the latest [`Change`]s to the
264    /// [`Buffer`].
265    ///
266    /// The list of [`Range`]s is the collection of [`Range`]s that
267    /// were requested to be updated and are within the printed region
268    /// of the [`Buffer`].
269    ///
270    /// Do note that, if more regions become visible on the screen
271    /// (this could happen if a [`Conceal`] tag is placed, for
272    /// example), this function will be called again, until the whole
273    /// screen has been parsed by every [`Parser`]
274    ///
275    /// # NOTES
276    ///
277    /// One other thing to note is that the `on` [range] is just a
278    /// suggestion. In most circumstances, it would be a little
279    /// convenient to go slightly over that range. For example, a
280    /// regex searcher should look only at the range provided, but if
281    /// a match goes slightly beyond the [range], it is fine to add
282    /// [`Tag`]s in there.
283    ///
284    /// Finally, keep in mind that [`Tag`]s are not allowed to be
285    /// repeated, and you can use this to your advantage, as in,
286    /// instead of checking if you need to place a [`Tag`] in a
287    /// certain spot, you can just place it, and Duat will ignore that
288    /// request if that [`Tag`] was already there.
289    ///
290    /// [`Tag`]: crate::text::Tag
291    /// [`Buffer`]: crate::buffer::Buffer
292    /// [`Change`]: crate::text::Change
293    /// [range]: std::ops::Range
294    /// [`parse`]: Parser::parse
295    /// [`Conceal`]: crate::text::Conceal
296    fn update(&mut self, pa: &mut Pass, buffer: &Handle, on: Vec<Range<Point>>) {}
297
298    /// Prepare this [`Parser`] before [`Buffer::read_parser`] call
299    ///
300    /// The [`Buffer::read_parser`]/[`Buffer::write_parser`] functions
301    /// block the current thread until the [`Parser`] is
302    /// available. Therefore, [`before_get`] should finish _all_
303    /// parsing, so if the parsing is taking place in
304    /// another thread, you're gonna want to join said thread and
305    /// finish it.
306    ///
307    /// If the [`Parser`]'s availability doesn't rely on other threads
308    /// (which should be the case for almost every single [`Parser`]),
309    /// then this function can just be left empty.
310    ///
311    /// [`before_get`]: Parser::before_get
312    fn before_get(&mut self) {
313        self.parse();
314    }
315
316    /// Prepare the [`Parser`] before [`Buffer::try_read_parser`] call
317    ///
318    /// The purpose of [`try_read_parser`], unlike [`read_parser`], is
319    /// to _only_ call the function passed if the [`Parser`] is ready
320    /// to be read. If it relies on a thread finishing its processing,
321    /// this function should return `true` _only_ if said thread is
322    /// ready to be merged.
323    ///
324    /// If the [`Parser`]'s availability doesn't rely on other threads
325    /// (which should be the case for almost every single [`Parser`]),
326    /// then this function should just return `true` all the time.
327    ///
328    /// [`try_read_parser`]: Buffer::try_read_parser
329    /// [`read_parser`]: Buffer::read_parser
330    fn before_try_get(&mut self) -> bool {
331        self.before_get();
332        true
333    }
334}
335
336#[derive(Default)]
337pub(super) struct Parsers {
338    list: RefCell<Vec<ParserParts>>,
339}
340
341impl Parsers {
342    /// Attempts to add  a [`Parser`]
343    pub(super) fn add<P: Parser>(
344        &self,
345        buffer: &Buffer,
346        f: impl FnOnce(BufferTracker) -> P,
347    ) -> Result<(), Text> {
348        let mut parsers = self.list.borrow_mut();
349        if parsers.iter().any(|rb| rb.ty == TypeId::of::<P>()) {
350            Err(txt!(
351                "There is already a parser of type [a]{}",
352                crate::utils::duat_name::<P>()
353            ))?;
354        }
355
356        let update_requested = Arc::new(AtomicBool::new(false));
357        let ranges = Arc::new(Mutex::new(RangesTracker::Manual(Ranges::new(
358            0..buffer.bytes().len().byte(),
359        ))));
360
361        let tracker = BufferTracker {
362            bytes: buffer.bytes().clone(),
363            opts: buffer.sync_opts.clone(),
364            fetcher: buffer.text.history().unwrap().new_fetcher(),
365            moment: Moment::default(),
366            ranges: ranges.clone(),
367            update_requested: update_requested.clone(),
368        };
369
370        parsers.push(ParserParts {
371            parser: Some(Box::new(f(tracker))),
372            ranges: ranges.clone(),
373            update_requested,
374            ty: TypeId::of::<P>(),
375        });
376
377        Ok(())
378    }
379
380    /// Reads a specific [`Parser`]
381    pub(super) fn read_parser<P: Parser, Ret>(&self, read: impl FnOnce(&P) -> Ret) -> Option<Ret> {
382        let position = self.list.borrow().iter().position(type_eq::<P>);
383        if let Some(i) = position {
384            let mut parser = self.list.borrow_mut()[i].parser.take()?;
385
386            parser.before_get();
387
388            let ptr: *const dyn Parser = &*parser;
389            let ret = read(unsafe { (ptr as *const P).as_ref() }.unwrap());
390
391            self.list.borrow_mut()[i].parser = Some(parser);
392
393            Some(ret)
394        } else {
395            None
396        }
397    }
398
399    /// Tries to read from a specific [`Parser`]. Fails if it is not
400    /// available
401    pub(super) fn try_read_parser<P: Parser, Ret>(
402        &self,
403        read: impl FnOnce(&P) -> Ret,
404    ) -> Option<Ret> {
405        let position = self.list.borrow().iter().position(type_eq::<P>);
406        if let Some(i) = position {
407            let mut parser = self.list.borrow_mut()[i].parser.take()?;
408
409            let ptr: *const dyn Parser = &*parser;
410            let ret = parser
411                .before_try_get()
412                .then(|| read(unsafe { (ptr as *const P).as_ref() }.unwrap()));
413
414            self.list.borrow_mut()[i].parser = Some(parser);
415
416            ret
417        } else {
418            None
419        }
420    }
421
422    /// Writes to a specific [`Parser`]
423    pub(super) fn write_parser<P: Parser, Ret>(
424        &self,
425        write: impl FnOnce(&mut P) -> Ret,
426    ) -> Option<Ret> {
427        let position = self.list.borrow().iter().position(type_eq::<P>);
428        if let Some(i) = position {
429            let mut parser = self.list.borrow_mut()[i].parser.take()?;
430
431            parser.before_get();
432
433            let ptr: *const dyn Parser = &*parser;
434            let ret = write(unsafe { (ptr as *mut P).as_mut() }.unwrap());
435
436            self.list.borrow_mut()[i].parser = Some(parser);
437
438            Some(ret)
439        } else {
440            None
441        }
442    }
443
444    /// Tries to write to a specific [`Parser`]. Fails if it is not
445    /// available
446    pub(super) fn try_write_parser<P: Parser, Ret>(
447        &self,
448        write: impl FnOnce(&mut P) -> Ret,
449    ) -> Option<Ret> {
450        let position = self.list.borrow().iter().position(type_eq::<P>);
451        if let Some(i) = position {
452            let mut parser = self.list.borrow_mut()[i].parser.take()?;
453
454            let ptr: *const dyn Parser = &*parser;
455            let ret = parser
456                .before_try_get()
457                .then(|| write(unsafe { (ptr as *mut P).as_mut() }.unwrap()));
458
459            self.list.borrow_mut()[i].parser = Some(parser);
460
461            ret
462        } else {
463            None
464        }
465    }
466
467    /// Updates the [`Parser`]s on a given range
468    // TODO: Deal with reparsing if Changes took place.
469    pub(super) fn update(&self, pa: &mut Pass, handle: &Handle, on: Range<usize>) {
470        let len = self.list.borrow().len();
471        for i in 0..len {
472            let mut parts = self.list.borrow_mut().remove(i);
473            let parser = parts.parser.as_mut().unwrap();
474
475            if parser.parse() {
476                let ranges_to_update = parts
477                    .ranges
478                    .lock()
479                    .remove(on.clone(), handle.read(pa).bytes());
480
481                parser.update(pa, handle, ranges_to_update)
482            }
483
484            parts.update_requested.store(false, Ordering::Relaxed);
485
486            self.list.borrow_mut().insert(i, parts)
487        }
488    }
489
490    /// Wether this [`Parsers`] is ready to be updated
491    pub fn needs_update(&self) -> bool {
492        let parsers = self.list.borrow();
493
494        parsers
495            .iter()
496            .any(|parts| parts.update_requested.load(Ordering::Relaxed))
497    }
498}
499
500/// Things related to an individual [`Parser`]
501struct ParserParts {
502    parser: Option<Box<dyn Parser>>,
503    ranges: Arc<Mutex<RangesTracker>>,
504    update_requested: Arc<AtomicBool>,
505    ty: TypeId,
506}
507
508/// A tracker for [`Change`]s that happen to a [`Buffer`]
509///
510/// [`Change`]: crate::text::Change
511#[derive(Debug)]
512pub struct BufferTracker {
513    bytes: Bytes,
514    opts: Arc<Mutex<PrintOpts>>,
515    fetcher: MomentFetcher,
516    moment: Moment,
517    ranges: Arc<Mutex<RangesTracker>>,
518    update_requested: Arc<AtomicBool>,
519}
520
521impl BufferTracker {
522    /// Updates the inner [`Bytes`] and retrieves latest [`Moment`]
523    ///
524    /// [`Change`]: crate::text::Change
525    pub fn update(&mut self) {
526        self.moment = self.fetcher.get_moment();
527        for change in self.moment.changes() {
528            self.bytes.apply_change(change);
529            self.ranges.lock().apply_change(change, &self.bytes);
530        }
531    }
532
533    /// Request for the [`Buffer`] to call [`Parser::parse`]
534    ///
535    /// This will prompt the [`Buffer`] to be updated and only update
536    /// relevant [`Range`]s, i.e., those that actually show up on
537    /// area and that have been added by to the [`BufferTracker`] via
538    /// [`add_range`].
539    ///
540    /// [`add_range`]: Self::add_range
541    pub fn request_parse(&self) {
542        self.update_requested.store(true, Ordering::Relaxed);
543    }
544
545    ////////// Range tracking functions
546
547    /// Adds a byte/[`Point`] [`Range`] to be updated on
548    /// [`Parser::update`]
549    ///
550    /// This [`Range`] will be merged with other [`Ranges`] on the
551    /// list, and when a [parse is requested], the intersections
552    /// between the [`Ranges`] sent to this method and the [`Range`]
553    /// of the [`Text`] shown on area will be updated.
554    ///
555    /// For example, if you add the ranges  `3..20` and `50..87`, and
556    /// the range shown on area is `17..61`, then two calls to
557    /// [`Parser::update`] will be made, one with the range
558    /// `17..20` and one with the range `50..61`. After that, the
559    /// ranges `3..17` and `61..87` will remain on the list of
560    /// [`Range`]s to be updated
561    ///
562    /// [parse is requested]: Self::request_parse
563    pub fn add_range(&mut self, range: impl TextRange) {
564        let range = range.to_range(self.bytes.len().byte());
565        self.ranges.lock().add_range(range);
566    }
567
568    /// Same as [`add_range`], but add many [`Range`]s at once
569    ///
570    /// [`add_range`]: Self::add_range
571    pub fn add_ranges<R: TextRange>(&mut self, new_ranges: impl IntoIterator<Item = R>) {
572        let mut ranges = self.ranges.lock();
573        for range in new_ranges {
574            let range = range.to_range(self.bytes.len().byte());
575            ranges.add_range(range);
576        }
577    }
578
579    /// Automatically add every [`Change`]'s [added range] to update
580    ///
581    /// This function turns on automatic [`Range`] addition for every
582    /// [`Change`] that takes place. You can still add [`Range`]s
583    /// manually through [`add_range`].
584    ///
585    /// [added range]: Change::added_range
586    /// [`add_range`]: BufferTracker::add_range
587    pub fn track_changed_ranges(&mut self) {
588        let mut tracker = self.ranges.lock();
589        *tracker = RangesTracker::ChangedRanges(tracker.take_ranges());
590    }
591
592    /// Automatically add every changed line to the ranges to update
593    ///
594    /// This function turns on automatic [`Range`] addition for every
595    /// line that a [`Change`]'s [added range] belongs to. You can
596    /// still add [`Range`]s manually through [`add_range`].
597    ///
598    /// It's probably the most common type of automatic range tracking
599    /// that you'd want, since, for example, regex patterns are very
600    /// convenient to separate line-wise, since most of them don't
601    /// tend to go over lines.
602    ///
603    /// Additionally, this option will also make it so only _whole
604    /// lines_ are updated. For example, if a line is partially cutoff
605    /// from the area, the range passed to [`Parser::update`] will
606    /// include the parts of the line that are outside of the area.
607    /// For the other tracking options, this won't be the case.
608    ///
609    /// [added range]: Change::added_range
610    /// [`add_range`]: BufferTracker::add_range
611    pub fn track_changed_lines(&mut self) {
612        let mut tracker = self.ranges.lock();
613        *tracker = RangesTracker::ChangedLines(tracker.take_ranges());
614    }
615
616    /// Always update the whole area
617    ///
618    /// This function basically turns off [`Range`] tracking and
619    /// assumes that you want to update the whole printed area.
620    ///
621    /// One very common usecase of this is to do with parsing the
622    /// [`Selections`]. You may want to, for example, do something for
623    /// every selection that is visible on screen, maybe something
624    /// like this:
625    ///
626    /// ```rust
627    /// # duat_core::doc_duat!(duat);
628    /// use duat::prelude::*;
629    ///
630    /// // When construction the SelectionLen, I turned on area tracking
631    /// struct SelectionLen {
632    ///     _tracker: BufferTracker,
633    ///     tagger: Tagger,
634    /// }
635    ///
636    /// impl Parser for SelectionLen {
637    ///     fn update(&mut self, pa: &mut Pass, buffer: &Handle, on: Vec<Range<Point>>) {
638    ///         let mut parts = buffer.text_mut(pa).parts();
639    ///         // This is efficient even in very large `Text`s.
640    ///         parts.tags.remove(self.tagger, ..);
641    ///
642    ///         for range in on {
643    ///             for (_, selection, is_main) in parts.selections.iter_within(range) {
644    ///                 let range = selection.byte_range(&parts.bytes);
645    ///                 let (start, end) = (range.start, range.end);
646    ///                 let len = end - start;
647    ///
648    ///                 if len > 2 {
649    ///                     let nums = len.ilog10() as usize + 1;
650    ///                     let ghost = Ghost(if is_main {
651    ///                         txt!("[sel_len.main]{len}")
652    ///                     } else {
653    ///                         txt!("[sel_len]{len}")
654    ///                     });
655    ///
656    ///                     parts.tags.insert(self.tagger, start, ghost);
657    ///                     parts.tags.insert(self.tagger, start..start + nums, Conceal);
658    ///                 }
659    ///             }
660    ///         }
661    ///     }
662    /// }
663    /// ```
664    ///
665    /// This function will make it so, for every visible
666    /// [`Selection`], its length in bytes will be displayed within
667    /// that selection with the `"sel_len"` [`Form`].
668    ///
669    /// # Note
670    ///
671    /// This function is actually incorrect. It doesn't take into
672    /// account the possibility of intercepting newlines or the
673    /// number being outside the printed area. The corrected version
674    /// would be much too long for a simple example.
675    ///
676    /// [`Selection`]: crate::mode::Selection
677    /// [`Selections`]: crate::mode::Selections
678    /// [`Form`]: crate::form::Form
679    pub fn track_area(&mut self) {
680        *self.ranges.lock() = RangesTracker::Area;
681    }
682
683    /// Disable the automatic [`Change`] tracking functionality
684    ///
685    /// This makes it so no [`Range`]s to update are added
686    /// automatically whenever a [`Change`] takes place. Instead, they
687    /// all must be added through [`add_range`].
688    ///
689    /// This is the default method of tracking [`Change`]s.
690    ///
691    /// [`add_range`]: BufferTracker::add_range
692    pub fn turn_off_tracking(&mut self) {
693        let mut tracker = self.ranges.lock();
694        *tracker = RangesTracker::Manual(tracker.take_ranges());
695    }
696
697    ////////// Querying functions
698
699    /// The [`Bytes`], as they are since the last call to [`update`]
700    ///
701    /// Do note that, because this tracks calls to [`update`], this
702    /// version of the [`Bytes`] may not reflect what the [`Bytes`]
703    /// look like in the [`Buffer`] _right now_, as more [`Change`]s
704    /// could have taken place since the last call.
705    ///
706    /// [`update`]: Self::update
707    /// [`Change`]: crate::text::Change
708    pub fn bytes(&self) -> &Bytes {
709        &self.bytes
710    }
711
712    /// The last [`Moment`] that was processed
713    ///
714    /// This is **not** the last [`Moment`] sent to the [`Buffer`],
715    /// nor does it necessarily correspond to a [`Moment`] in the
716    /// [`Text`]'s history. It's just a collection of [`Change`]s that
717    /// took place in between calls to [`Self::update`].
718    ///
719    /// [`Change`]: crate::text::Change
720    pub fn moment(&self) -> &Moment {
721        &self.moment
722    }
723
724    /// The indentation in the line at a [`Point`]
725    ///
726    /// This value only takes ascii spaces and tabs into account,
727    /// which may differ from the value from [`Text::indent`],
728    /// since that one calculates the indent through the [`Area`],
729    /// while this one only makes use of the [`Buffer`]'s
730    /// [`PrintOpts`].
731    ///
732    /// [`Area`]: crate::ui::Area
733    pub fn indent(&self, p: Point) -> usize {
734        self.bytes.indent(p, *self.opts.lock())
735    }
736
737    /// The [`PrintOpts`] of the [`Buffer`]
738    ///
739    /// Unlike the other parts of this struct, the [`PrintOpts`] will
740    /// always be up to date with what it currently is in the
741    /// [`Buffer`]
742    pub fn opts(&self) -> PrintOpts {
743        *self.opts.lock()
744    }
745}
746
747/// Tracker for which [`Range`]s to update
748#[derive(Debug)]
749enum RangesTracker {
750    Manual(Ranges),
751    ChangedRanges(Ranges),
752    ChangedLines(Ranges),
753    Area,
754}
755
756impl RangesTracker {
757    /// Manually adds a [`Range`] to be tracked
758    #[track_caller]
759    fn add_range(&mut self, range: Range<usize>) {
760        match self {
761            RangesTracker::Manual(ranges)
762            | RangesTracker::ChangedRanges(ranges)
763            | RangesTracker::ChangedLines(ranges) => ranges.add(range),
764            RangesTracker::Area => {}
765        }
766    }
767
768    /// Applies a [`Change`] to the [`Range`]s within
769    fn apply_change(&mut self, change: Change<&str>, bytes: &Bytes) {
770        match self {
771            RangesTracker::Manual(ranges) => {
772                ranges.shift_by(change.start().byte(), change.shift()[0])
773            }
774            RangesTracker::ChangedRanges(ranges) => {
775                ranges.shift_by(change.start().byte(), change.shift()[0]);
776                ranges.add(change.start().byte()..change.added_end().byte())
777            }
778            RangesTracker::ChangedLines(ranges) => {
779                ranges.shift_by(change.start().byte(), change.shift()[0]);
780                let start = bytes.point_at_line(change.start().line());
781                let end =
782                    bytes.point_at_line((change.added_end().line() + 1).min(bytes.len().line()));
783                ranges.add(start.byte()..end.byte());
784            }
785            RangesTracker::Area => {}
786        }
787    }
788
789    /// Takes the [`Ranges`] from the tracker
790    fn take_ranges(&mut self) -> Ranges {
791        match self {
792            RangesTracker::Manual(ranges)
793            | RangesTracker::ChangedRanges(ranges)
794            | RangesTracker::ChangedLines(ranges) => std::mem::take(ranges),
795            RangesTracker::Area => Ranges::empty(),
796        }
797    }
798
799    /// Gets the list of [`Range`]s that need to be updated
800    #[track_caller]
801    fn remove(&mut self, range: Range<usize>, bytes: &Bytes) -> Vec<Range<Point>> {
802        match self {
803            RangesTracker::Manual(ranges)
804            | RangesTracker::ChangedRanges(ranges)
805            | RangesTracker::ChangedLines(ranges) => ranges
806                .remove(range)
807                .map(|r| bytes.point_at_byte(r.start)..bytes.point_at_byte(r.end))
808                .collect(),
809            RangesTracker::Area => {
810                vec![bytes.point_at_byte(range.start)..bytes.point_at_byte(range.end)]
811            }
812        }
813    }
814}
815
816/// Wether the type of the [`ParserParts`]'s parser is `P`
817fn type_eq<P: 'static>(parts: &ParserParts) -> bool {
818    parts.ty == TypeId::of::<P>()
819}