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}