duat_core/context/
handles.rs

1//! Widget handles for Duat
2//!
3//! These are used pretty much everywhere, and are essentially just an
4//! [`RwData<W>`] conjoined to an [`Ui::Area`].
5
6use std::{
7    any::TypeId,
8    cell::{Cell, RefCell, RefMut},
9    rc::Rc,
10};
11
12use lender::Lender;
13
14use super::FileParts;
15use crate::{
16    cfg::PrintCfg,
17    data::{Pass, RwData},
18    file::File,
19    mode::{Cursor, Cursors, Selection, Selections},
20    text::{Point, Searcher, Text, TwoPoints},
21    ui::{Node, RawArea, Ui, Widget},
22};
23
24/// A handle to a [`File`] widget
25///
26/// This handle acts much like an [`RwData<File>`], but it also
27/// includes an [`Area`] that can be acted upon alongside the
28/// [`File`].
29///
30/// This is the only way you are supposed to read information about
31/// the [`File`], in order to display it on [`Widget`]s, create
32/// [`Text`]s, and do all sorts of things. You can, of course, also
33/// modify a [`File`] from within this struct, but you should be
34/// careful to prevent infinite loops, where you modify a [`File`], it
35/// gets updated, and then you modify it again after noticing that it
36/// has changed.
37///
38/// The main difference between a [`FileHandle<U>`] and a
39/// [`Handle<File<U>, U>`] is that the [`Handle`] is capable of acting
40/// on selections, but is fixed to just one [`File`], while the
41/// [`FileHandle`] can automatically point to the current [`File`].
42///
43/// [`Area`]: crate::ui::RawArea
44/// [`Text`]: crate::text::Text
45#[derive(Clone)]
46pub struct FileHandle<U: Ui> {
47    fixed: Option<FileParts<U>>,
48    current: RwData<Option<FileParts<U>>>,
49}
50
51impl<U: Ui> FileHandle<U> {
52    /// Returns a new [`FileHandle`] from its parts
53    pub(crate) fn from_parts(
54        fixed: Option<FileParts<U>>,
55        current: RwData<Option<FileParts<U>>>,
56    ) -> Self {
57        Self { fixed, current }
58    }
59
60    /// Reads from the [`File`] and the [`Area`] using a [`Pass`]
61    ///
62    /// The consistent use of a [`Pass`] for the purposes of
63    /// reading/writing to the values of [`RwData`]s ensures that no
64    /// panic or invalid borrow happens at runtime, even while working
65    /// with untrusted code. More importantly, Duat uses these
66    /// guarantees in order to give the end user a ridiculous amount
67    /// of freedom in where they can do things, whilst keeping Rust's
68    /// number one rule and ensuring thread safety, even with a
69    /// relatively large amount of shareable state.
70    ///
71    /// # Panics
72    ///
73    /// Panics if there is a mutable borrow of this struct somewhere,
74    /// which could happen if you use [`RwData::write_unsafe`] or
75    /// [`RwData::write_unsafe_as`] from some other place
76    ///
77    /// [`Area`]: crate::ui::RawArea
78    pub fn read<Ret>(&self, pa: &Pass, f: impl FnOnce(&File<U>, &U::Area) -> Ret) -> Ret {
79        if let Some((handle, _)) = self.fixed.as_ref() {
80            f(&handle.widget.acquire(pa), &handle.area)
81        } else {
82            self.current.read(pa, |parts| {
83                let (handle, _) = parts.as_ref().unwrap();
84                f(&handle.widget.acquire(pa), &handle.area)
85            })
86        }
87    }
88
89    /// Writes to the [`File`] and [`Area`] within using a [`Pass`]
90    ///
91    /// The consistent use of a [`Pass`] for the purposes of
92    /// reading/writing to the values of [`RwData`]s ensures that no
93    /// panic or invalid borrow happens at runtime, even while working
94    /// with untrusted code. More importantly, Duat uses these
95    /// guarantees in order to give the end user a ridiculous amount
96    /// of freedom in where they can do things, whilst keeping Rust's
97    /// number one rule and ensuring thread safety, even with a
98    /// relatively large amount of shareable state.
99    ///
100    /// # Panics
101    ///
102    /// Panics if there is any type of borrow of this struct
103    /// somewhere, which could happen if you use
104    /// [`RwData::read_unsafe`] or [`RwData::write_unsafe`], for
105    /// example.
106    ///
107    /// [`Area`]: crate::ui::RawArea
108    pub fn write<Ret>(&self, pa: &mut Pass, f: impl FnOnce(&mut File<U>, &U::Area) -> Ret) -> Ret {
109        if let Some((handle, _)) = self.fixed.as_ref() {
110            f(&mut handle.widget.acquire_mut(pa), &handle.area)
111        } else {
112            // SAFETY: Since the update closure only uses a write method, the
113            // Pass becomes unusable for other purposes, making it impossible
114            // to make further borrows, asserting that there is no other borrow
115            // for self.current.
116            unsafe {
117                self.current.read_unsafe(|parts| {
118                    let (handle, _) = parts.as_ref().unwrap();
119                    f(&mut handle.widget.acquire_mut(pa), &handle.area)
120                })
121            }
122        }
123    }
124
125    /// Reads a [`Widget`] related to this [`File`], alongside its
126    /// [`Area`], with a [`Pass`]
127    ///
128    /// A related [`Widget`] is one that was pushed to this [`File`]
129    /// during the [`OnFileOpen`] [hook].
130    ///
131    /// [`Area`]: crate::ui::Area
132    /// [`OnFileOpen`]: crate::hook::OnFileOpen
133    /// [hook]: crate::hook
134    pub fn read_related<W: 'static, R>(
135        &self,
136        pa: &Pass,
137        f: impl FnOnce(&W, &U::Area) -> R,
138    ) -> Option<R> {
139        let read = |(handle, related): &FileParts<U>| {
140            if TypeId::of::<W>() == TypeId::of::<File<U>>() {
141                let area = handle.area();
142                handle.widget().read_as(pa, |w| f(w, area))
143            } else {
144                let related = related.acquire(pa);
145                related
146                    .iter()
147                    .find(|node| node.data_is::<W>())
148                    .and_then(|node| node.widget().read_as(pa, |w| f(w, node.area())))
149            }
150        };
151
152        if let Some(parts) = self.fixed.as_ref() {
153            read(parts)
154        } else {
155            self.current.read(pa, |parts| read(parts.as_ref().unwrap()))
156        }
157    }
158
159    /// Gets the [`RwData`] and [`Area`] of a related widget, with a
160    /// [`Pass`]
161    ///
162    /// A related [`Widget`] is one that was pushed to this [`File`]
163    /// during the [`OnFileOpen`] [hook].
164    ///
165    /// [`Area`]: crate::ui::Area
166    /// [`OnFileOpen`]: crate::hook::OnFileOpen
167    /// [hook]: crate::hook
168    pub fn get_related_widget<W: Widget<U> + 'static>(&self, pa: &Pass) -> Option<Handle<W, U>> {
169        let get_related = |(handle, related): &FileParts<U>| {
170            if TypeId::of::<W>() == TypeId::of::<File<U>>() {
171                let widget = handle.widget().try_downcast()?;
172                Some(Handle::from_parts(
173                    widget,
174                    handle.area().clone(),
175                    handle.mask().clone(),
176                ))
177            } else {
178                related.read(pa, |related| {
179                    related.iter().find_map(|node| {
180                        let (widget, area, mask, _) = node.parts();
181                        widget
182                            .try_downcast()
183                            .map(|data| Handle::from_parts(data, area.clone(), mask.clone()))
184                    })
185                })
186            }
187        };
188
189        if let Some(parts) = self.fixed.as_ref() {
190            get_related(parts)
191        } else {
192            self.current
193                .read(pa, |parts| get_related(parts.as_ref().unwrap()))
194        }
195    }
196
197    /// Writes to the related widgets
198    pub(crate) fn write_related_widgets(&self, pa: &mut Pass, f: impl FnOnce(&mut Vec<Node<U>>)) {
199        if let Some((.., related)) = self.fixed.as_ref() {
200            related.write(pa, f)
201        } else {
202            // SAFETY: Same situation as the write method
203            unsafe {
204                self.current
205                    .read_unsafe(|parts| parts.as_ref().unwrap().1.write(pa, f))
206            }
207        }
208    }
209
210    ////////// Querying functions
211
212    /// Gets a [`Handle`] from this [`FileHandle`]
213    pub fn handle(&self, pa: &Pass) -> Handle<File<U>, U> {
214        if let Some((handle, _)) = self.fixed.as_ref() {
215            handle.clone()
216        } else {
217            self.current.acquire(pa).as_ref().unwrap().0.clone()
218        }
219    }
220
221    /// Wether someone else called [`write`] or [`write_as`] since the
222    /// last [`read`] or [`write`]
223    ///
224    /// Do note that this *DOES NOT* mean that the value inside has
225    /// actually been changed, it just means a mutable reference was
226    /// acquired after the last call to [`has_changed`].
227    ///
228    /// Some types like [`Text`], and traits like [`Widget`] offer
229    /// [`needs_update`] methods, you should try to determine what
230    /// parts to look for changes.
231    ///
232    /// Generally though, you can use this method to gauge that.
233    ///
234    /// [`write`]: RwData::write
235    /// [`write_as`]: RwData::write_as
236    /// [`read`]: RwData::read
237    /// [`has_changed`]: RwData::has_changed
238    /// [`Text`]: crate::text::Text
239    /// [`Widget`]: crate::ui::Widget
240    /// [`needs_update`]: crate::ui::Widget::needs_update
241    pub fn has_changed(&self) -> bool {
242        if let Some((handle, _)) = self.fixed.as_ref() {
243            handle.has_changed()
244        } else {
245            self.current.has_changed()
246                || self.current.read_raw(|parts| {
247                    let (handle, _) = parts.as_ref().unwrap();
248                    handle.has_changed()
249                })
250        }
251    }
252
253    /// Wether the [`File`] within has swapped to another
254    ///
255    /// This can only happen when this is a
256    pub fn has_swapped(&self) -> bool {
257        let has_changed = self.current.has_changed();
258        self.current.declare_as_read();
259        has_changed
260    }
261
262    /// Wether the [`RwData`] within and another point to the same
263    /// value
264    pub fn ptr_eq<T: ?Sized>(&self, pa: &Pass, other: &RwData<T>) -> bool {
265        if let Some((handle, ..)) = self.fixed.as_ref() {
266            handle.ptr_eq(other)
267        } else {
268            self.current
269                .read(pa, |parts| parts.as_ref().unwrap().0.ptr_eq(other))
270        }
271    }
272
273    /// The name of the [`File`] in question
274    pub fn name(&self, pa: &Pass) -> String {
275        if let Some((handle, ..)) = self.fixed.as_ref() {
276            handle.read(pa, |f, _| f.name())
277        } else {
278            self.current.read(pa, |parts| {
279                parts.as_ref().unwrap().0.read(pa, |f, _| f.name())
280            })
281        }
282    }
283
284    /// The path of the [`File`] in question
285    pub fn path(&self, pa: &Pass) -> String {
286        if let Some((handle, ..)) = self.fixed.as_ref() {
287            handle.read(pa, |f, _| f.path())
288        } else {
289            self.current.read(pa, |parts| {
290                parts.as_ref().unwrap().0.read(pa, |f, _| f.path())
291            })
292        }
293    }
294
295    /// The path of the [`File`] in question, if it was set
296    pub fn set_path(&self, pa: &Pass) -> Option<String> {
297        if let Some((handle, ..)) = self.fixed.as_ref() {
298            handle.read(pa, |f, _| f.path_set())
299        } else {
300            self.current.read(pa, |parts| {
301                parts.as_ref().unwrap().0.read(pa, |f, _| f.path_set())
302            })
303        }
304    }
305}
306
307/// A handle to a [`Widget`] in Duat
308///
309/// The [`Handle`] lets you do all sorts of edits on a [`Widget`]. You
310/// can, for example, make use of the [`Selection`]s in its [`Text`]
311/// in order to edit the [`Text`] in a very declarative way.
312///
313/// One of the places where this is commonly done is within [`Mode`]s,
314/// where you get access to the [`Handle`] of the currently active
315/// [`Widget`]. Below is a very straightforward [`Mode`]:
316///
317/// ```rust
318/// use duat_core::prelude::*;
319/// /// A very basic example Mode.
320/// #[derive(Clone)]
321/// struct PlacesCharactersAndMoves;
322///
323/// impl<U: Ui> Mode<U> for PlacesCharactersAndMoves {
324///     type Widget = File<U>;
325///
326///     // ...
327///     fn send_key(&mut self, _: &mut Pass, _: KeyEvent, _: Handle<Self::Widget, U>) {
328///         todo!();
329///     }
330/// }
331/// ```
332///
333/// In order to modify the widget, you must implement the
334/// [`Mode::send_key`] method. In it, you receive the following:
335///
336/// - A [`&mut Pass`], which will give you access to all of duat's
337///   shared state;
338/// - The [key] that was sent, may be a [mapped] key.
339/// - The [`Handle`] for a [`Mode::Widget`].
340///
341/// ```rust
342/// use duat_core::prelude::*;
343/// #[derive(Clone)]
344/// struct PlacesCharactersAndMoves;
345/// impl<U: Ui> Mode<U> for PlacesCharactersAndMoves {
346///     type Widget = File<U>;
347///
348///     fn send_key(&mut self, pa: &mut Pass, key: KeyEvent, handle: Handle<File<U>, U>) {
349///         match key {
350///             // actions based on the key pressed
351///             key!(KeyCode::Char('c')) => {
352///                 // Do something when the character 'c' is typed.
353///             }
354///             _ => todo!("The remaining keys"),
355///         }
356///     }
357/// }
358/// ```
359///
360/// (You can use the [`key!`] macro in order to match [`KeyEvent`]s).
361///
362/// With the [`Handle`], you can modify [`Text`] in a simplified
363/// way. This is done by two actions, [editing] and [moving]. You
364/// can only do one of these on any number of selections at the same
365/// time.
366///
367/// ```rust
368/// # use duat_core::prelude::*;
369/// # #[derive(Clone)]
370/// # struct PlacesCharactersAndMoves;
371/// impl<U: Ui> Mode<U> for PlacesCharactersAndMoves {
372/// #   type Widget = File<U>;
373///     /* ... */
374///     fn send_key(&mut self, pa: &mut Pass, key: KeyEvent, handle: Handle<Self::Widget, U>) {
375///         match key {
376///             key!(KeyCode::Char(c)) => {
377///                 handle.edit_all(pa, |mut e| {
378///                     e.insert('c');
379///                     e.move_hor(1);
380///                 });
381///             },
382///             key!(KeyCode::Right, KeyMod::SHIFT) => {
383///                 handle.edit_all(pa, |mut e| {
384///                     if e.anchor().is_none() {
385///                         e.set_anchor();
386///                     }
387///                     e.move_hor(1);
388///                 });
389///             }
390///             key!(KeyCode::Right) => {
391///                 handle.edit_all(pa, |mut e| {
392///                     e.unset_anchor();
393///                     e.move_hor(1);
394///                 });
395///             }
396///             _ => todo!("Predictable remaining implementations")
397///         }
398///     }
399/// # }
400/// ```
401///
402/// [`Mode`]: crate::mode::Mode
403/// [`Mode::Widget`]: crate::mode::Mode::Widget
404/// [`&mut Pass`]: Pass
405/// [`PromptLine`]: https://docs.rs/duat-utils/latest/duat_utils/widgets/struct.PromptLine.html
406/// [`Mode::send_key`]: crate::mode::Mode::send_key
407/// [key]: crate::mode::KeyEvent
408/// [mapped]: crate::mode::map
409/// [`read`]: RwData::read
410/// [`write`]: RwData::write
411/// [`U::Area`]: Ui::Area
412/// [`Self::Widget`]: crate::mode::Mode::Widget
413/// [`Some(selections)`]: Some
414/// [`Ui::Area`]: crate::ui::Ui::Area
415/// [commands]: crate::cmd
416/// [`key!`]: crate::mode::key
417/// [`KeyEvent`]: crate::mode::KeyEvent
418/// [editing]: Cursor
419/// [moving]: Cursor
420/// [`Mode`]: crate::mode::Mode
421/// [`U::Area`]: Ui::Area
422#[derive(Debug)]
423pub struct Handle<W: Widget<U> + ?Sized, U: Ui, S = ()> {
424    widget: RwData<W>,
425    area: U::Area,
426    mask: Rc<Cell<&'static str>>,
427    searcher: RefCell<S>,
428}
429
430impl<W: Widget<U> + ?Sized, U: Ui> Handle<W, U> {
431    /// Returns a new instance of a [`Handle<W, U>`]
432    pub(crate) fn from_parts(
433        widget: RwData<W>,
434        area: U::Area,
435        mask: Rc<Cell<&'static str>>,
436    ) -> Self {
437        Self {
438            widget,
439            area,
440            mask,
441            searcher: RefCell::new(()),
442        }
443    }
444}
445
446impl<W: Widget<U> + ?Sized, U: Ui, S> Handle<W, U, S> {
447    /// Reads from the [`Widget`] and the [`Area`] using a [`Pass`]
448    ///
449    /// The consistent use of a [`Pass`] for the purposes of
450    /// reading/writing to the values of [`RwData`]s ensures that no
451    /// panic or invalid borrow happens at runtime, even while working
452    /// with untrusted code. More importantly, Duat uses these
453    /// guarantees in order to give the end user a ridiculous amount
454    /// of freedom in where they can do things, whilst keeping Rust's
455    /// number one rule and ensuring thread safety, even with a
456    /// relatively large amount of shareable state.
457    ///
458    /// # Panics
459    ///
460    /// Panics if there is a mutable borrow of this struct somewhere,
461    /// which could happen if you use [`RwData::write_unsafe`] or
462    /// [`RwData::write_unsafe_as`] from some other place
463    ///
464    /// [`Area`]: crate::ui::RawArea
465    pub fn read<Ret>(&self, pa: &Pass, f: impl FnOnce(&W, &U::Area) -> Ret) -> Ret {
466        f(&self.widget.acquire(pa), &self.area)
467    }
468
469    /// Writes to the [`Widget`] and [`Area`] within using a [`Pass`]
470    ///
471    /// The consistent use of a [`Pass`] for the purposes of
472    /// reading/writing to the values of [`RwData`]s ensures that no
473    /// panic or invalid borrow happens at runtime, even while working
474    /// with untrusted code. More importantly, Duat uses these
475    /// guarantees in order to give the end user a ridiculous amount
476    /// of freedom in where they can do things, whilst keeping Rust's
477    /// number one rule and ensuring thread safety, even with a
478    /// relatively large amount of shareable state.
479    ///
480    /// # Panics
481    ///
482    /// Panics if there is any type of borrow of this struct
483    /// somewhere, which could happen if you use
484    /// [`RwData::read_unsafe`] or [`RwData::write_unsafe`], for
485    /// example.
486    ///
487    /// [`Area`]: crate::ui::RawArea
488    pub fn write<Ret>(&self, pa: &mut Pass, f: impl FnOnce(&mut W, &U::Area) -> Ret) -> Ret {
489        f(&mut self.widget.acquire_mut(pa), &self.area)
490    }
491
492    ////////// Selection Editing functions
493
494    /// Edits the nth [`Selection`] in the [`Text`]
495    ///
496    /// Once dropped, the [`Selection`] in this [`Cursor`] will be
497    /// added back to the list of [`Selection`]s, unless it is
498    /// [destroyed]
499    ///
500    /// If you want to edit on the main selection, see [`edit_main`],
501    /// if you want to edit on many [`Selection`]s, see
502    /// [`edit_iter`].
503    ///
504    /// Just like all other `edit` methods, this one will populate the
505    /// [`Selections`], so if there are no [`Selection`]s, it will
506    /// create one at [`Point::default`].
507    ///
508    /// [destroyed]: Cursor::destroy
509    /// [`edit_main`]: Self::edit_main
510    /// [`edit_iter`]: Self::edit_iter
511    /// [`Point::default`]: crate::text::Point::default
512    pub fn edit_nth<Ret>(
513        &self,
514        pa: &mut Pass,
515        n: usize,
516        edit: impl FnOnce(Cursor<W, U::Area, S>) -> Ret,
517    ) -> Ret {
518        fn get_parts<'a, W: Widget<U> + ?Sized, U: Ui>(
519            pa: &mut Pass,
520            widget: &'a RwData<W>,
521            n: usize,
522        ) -> (Selection, bool, RefMut<'a, W>) {
523            let mut widget = widget.acquire_mut(pa);
524            let selections = widget.text_mut().selections_mut().unwrap();
525            selections.populate();
526            let Some((selection, was_main)) = selections.remove(n) else {
527                panic!("Selection index {n} out of bounds");
528            };
529
530            (selection, was_main, widget)
531        }
532
533        let (selection, was_main, mut widget) = get_parts(pa, &self.widget, n);
534
535        // This is safe because of the &mut Pass argument
536        let mut searcher = self.searcher.borrow_mut();
537
538        edit(Cursor::new(
539            selection,
540            n,
541            was_main,
542            &mut *widget,
543            &self.area,
544            None,
545            &mut searcher,
546        ))
547    }
548
549    /// Edits the main [`Selection`] in the [`Text`]
550    ///
551    /// Once dropped, the [`Selection`] in this [`Cursor`] will be
552    /// added back to the list of [`Selection`]s, unless it is
553    /// [destroyed]
554    ///
555    /// If you want to edit on the `nth` selection, see [`edit_nth`],
556    /// same for [`edit_last`], if you want to edit on many
557    /// [`Selection`]s, see [`edit_iter`].
558    ///
559    /// Just like all other `edit` methods, this one will populate the
560    /// [`Selections`], so if there are no [`Selection`]s, it will
561    /// create one at [`Point::default`].
562    ///
563    /// [destroyed]: Cursor::destroy
564    /// [`edit_nth`]: Self::edit_nth
565    /// [`edit_last`]: Self::edit_last
566    /// [`edit_iter`]: Self::edit_iter
567    /// [`Point::default`]: crate::text::Point::default
568    pub fn edit_main<Ret>(
569        &self,
570        pa: &mut Pass,
571        edit: impl FnOnce(Cursor<W, U::Area, S>) -> Ret,
572    ) -> Ret {
573        self.edit_nth(
574            pa,
575            self.widget
576                .read(pa, |wid| wid.text().selections().unwrap().main_index()),
577            edit,
578        )
579    }
580
581    /// Edits the last [`Selection`] in the [`Text`]
582    ///
583    /// Once dropped, the [`Selection`] in this [`Cursor`] will be
584    /// added back to the list of [`Selection`]s, unless it is
585    /// [destroyed]
586    ///
587    /// If you want to edit on the `nth` selection, see [`edit_nth`],
588    /// same for [`edit_main`], if you want to edit on many
589    /// [`Selection`]s, see [`edit_iter`].
590    ///
591    /// Just like all other `edit` methods, this one will populate the
592    /// [`Selections`], so if there are no [`Selection`]s, it will
593    /// create one at [`Point::default`].
594    ///
595    /// [destroyed]: Cursor::destroy
596    /// [`edit_nth`]: Self::edit_nth
597    /// [`edit_main`]: Self::edit_main
598    /// [`edit_iter`]: Self::edit_iter
599    /// [`Point::default`]: crate::text::Point::default
600    pub fn edit_last<Ret>(
601        &self,
602        pa: &mut Pass,
603        edit: impl FnOnce(Cursor<W, U::Area, S>) -> Ret,
604    ) -> Ret {
605        self.edit_nth(
606            pa,
607            self.widget
608                .read(pa, |wid| wid.text().selections().unwrap().len())
609                .saturating_sub(1),
610            edit,
611        )
612    }
613
614    /// A [`Lender`] over all [`Cursor`]s of the [`Text`]
615    ///
616    /// This lets you easily iterate over all [`Selection`]s, without
617    /// having to worry about insertion affecting the order at which
618    /// they are edited (like what repeated calls to [`edit_nth`]
619    /// would do)
620    ///
621    /// Note however that you can't use a [`Lender`] (also known as a
622    /// lending iterator) in a `for` loop, but you should be able
623    /// to just `while let Some(e) = editors.next() {}` or
624    /// `handle.edit_iter().for_each(|_| {})` instead.
625    ///
626    /// Just like all other `edit` methods, this one will populate the
627    /// [`Selections`], so if there are no [`Selection`]s, it will
628    /// create one at [`Point::default`].
629    ///
630    /// [`edit_nth`]: Self::edit_nth
631    /// [`Point::default`]: crate::text::Point::default
632    pub fn edit_iter<Ret>(
633        &self,
634        pa: &mut Pass,
635        edit: impl FnOnce(Cursors<'_, W, U::Area, S>) -> Ret,
636    ) -> Ret {
637        edit(self.get_iter(pa))
638    }
639
640    /// A shortcut for iterating over all selections
641    ///
642    /// This is the equivalent of calling:
643    ///
644    /// ```rust
645    /// # use duat_core::prelude::*;
646    /// # fn test<U: Ui>(pa: &mut Pass, handle: Handle<File<U>, U, ()>) {
647    /// handle.edit_iter(pa, |iter| iter.for_each(|e| { /* .. */ }));
648    /// # }
649    /// ```
650    ///
651    /// But it can't return a value, and is meant to reduce the
652    /// indentation that will inevitably come from using the
653    /// equivalent long form call.
654    pub fn edit_all(&self, pa: &mut Pass, edit: impl FnMut(Cursor<W, U::Area, S>)) {
655        self.get_iter(pa).for_each(edit);
656    }
657
658    fn get_iter(&self, pa: &mut Pass) -> Cursors<'_, W, U::Area, S> {
659        let mut widget = self.widget.acquire_mut(pa);
660        let selections = widget.text_mut().selections_mut().unwrap();
661        selections.populate();
662
663        let searcher = self.searcher.borrow_mut();
664
665        Cursors::new(0, widget, &self.area, searcher)
666    }
667
668    ////////// Functions derived from RwData
669
670    /// Reads the [`Text`] of the [`Widget`]
671    pub fn read_text<Ret>(&self, pa: &Pass, read: impl FnOnce(&Text) -> Ret) -> Ret {
672        let widget = self.widget.acquire(pa);
673        read(widget.text())
674    }
675
676    /// Writes to the [`Text`] of the [`Widget`]
677    pub fn write_text<Ret>(&self, pa: &mut Pass, write: impl FnOnce(&mut Text) -> Ret) -> Ret {
678        let mut widget = self.widget.acquire_mut(pa);
679        write(widget.text_mut())
680    }
681
682    /// Reads the [`Selections`] of the [`Widget`]
683    pub fn read_selections<Ret>(&self, pa: &Pass, read: impl FnOnce(&Selections) -> Ret) -> Ret {
684        let widget = self.widget.acquire(pa);
685        read(widget.text().selections().unwrap())
686    }
687
688    /// Writes to the [`Selections`] of the [`Widget`]
689    pub fn write_selections<Ret>(
690        &self,
691        pa: &mut Pass,
692        write: impl FnOnce(&mut Selections) -> Ret,
693    ) -> Ret {
694        let mut widget = self.widget.acquire_mut(pa);
695        write(widget.text_mut().selections_mut().unwrap())
696    }
697
698    ////////// Direct Text manipulation
699
700    /// Clones the [`Text`] within
701    pub fn clone_text(&self, pa: &Pass) -> Text {
702        self.widget.clone_text(pa)
703    }
704
705    /// Replaces the [`Text`] within with a [`Default`] version
706    pub fn take_text(&self, pa: &mut Pass) -> Text {
707        self.widget.take_text(pa)
708    }
709
710    /// Replaces the [`Text`] of the [`Widget`], returning the
711    /// previous value
712    pub fn replace_text(&self, pa: &mut Pass, text: impl Into<Text>) -> Text {
713        self.widget.replace_text(pa, text.into())
714    }
715
716    /// Undoes the last moment in the history, if there is one
717    pub fn undo(&self, pa: &mut Pass) {
718        self.widget.write(pa, |wid| wid.text_mut().undo());
719    }
720
721    /// Redoes the last moment in the history, if there is one
722    pub fn redo(&self, pa: &mut Pass) {
723        self.widget.write(pa, |wid| wid.text_mut().redo());
724    }
725
726    /// Finishes the current moment and adds a new one to the history
727    pub fn new_moment(&self, pa: &mut Pass) {
728        self.widget.write(pa, |wid| wid.text_mut().new_moment());
729    }
730
731    ////////// Area functions
732
733    /// Scrolls the [`Text`] veritcally by an amount
734    ///
735    /// If [`PrintCfg.allow_overscroll`] is set, then the [`Text`]
736    /// will be allowed to scroll beyond the last line, up until
737    /// reaching the `scrolloff.y` value.
738    ///
739    /// [`PrintCfg.allow_overscroll`]: crate::cfg::PrintCfg::allow_overscroll
740    pub fn scroll_ver(&self, pa: &Pass, dist: i32) {
741        let widget = self.widget.acquire(pa);
742        self.area()
743            .scroll_ver(widget.text(), dist, widget.print_cfg());
744        self.widget.declare_written();
745    }
746
747    /// Scrolls the [`Text`] to the visual line of a [`TwoPoints`]
748    ///
749    /// If `scroll_beyond` is set, then the [`Text`] will be allowed
750    /// to scroll beyond the last line, up until reaching the
751    /// `scrolloff.y` value.
752    pub fn scroll_to_points(&self, pa: &Pass, points: impl TwoPoints) {
753        let widget = self.widget.acquire(pa);
754        self.area
755            .scroll_to_points(widget.text(), points, widget.print_cfg());
756        self.widget.declare_written();
757    }
758
759    /// The start points that should be printed
760    pub fn start_points(&self, pa: &Pass) -> (Point, Option<Point>) {
761        let widget = self.widget.acquire(pa);
762        self.area.start_points(widget.text(), widget.print_cfg())
763    }
764
765    /// The end points that should be printed
766    pub fn end_points(&self, pa: &Pass) -> (Point, Option<Point>) {
767        let widget = self.widget.acquire(pa);
768        self.area.end_points(widget.text(), widget.print_cfg())
769    }
770
771    ////////// Querying functions
772
773    /// This [`Handle`]'s [`Widget`]
774    pub fn widget(&self) -> &RwData<W> {
775        &self.widget
776    }
777
778    /// This [`Handle`]'s [`U::Area`]
779    ///
780    /// [`U::Area`]: crate::ui::Ui::Area
781    pub fn area(&self) -> &U::Area {
782        &self.area
783    }
784
785    /// Gets this [`Handle`]'s mask
786    ///
787    /// This mask is going to be used to map [`Form`]s to other
788    /// [`Form`]s when printing via [`Widget::print`]. To see more
789    /// about how masks work, see [`form::enable_mask`].
790    ///
791    /// [`Form`]: crate::form::Form
792    /// [`form::enable_mask`]: crate::form::enable_mask
793    pub fn mask(&self) -> &Rc<Cell<&'static str>> {
794        &self.mask
795    }
796
797    /// Sets this [`Handle`]'s mask, returning the previous one
798    ///
799    /// This mask is going to be used to map [`Form`]s to other
800    /// [`Form`]s when printing via [`Widget::print`]. To see more
801    /// about how masks work, see [`form::enable_mask`].
802    ///
803    /// [`Form`]: crate::form::Form
804    /// [`form::enable_mask`]: crate::form::enable_mask
805    pub fn set_mask(&self, mask: &'static str) -> &'static str {
806        self.widget.declare_written();
807        self.mask.replace(mask)
808    }
809
810    /// Wether someone else called [`write`] or [`write_as`] since the
811    /// last [`read`] or [`write`]
812    ///
813    /// Do note that this *DOES NOT* mean that the value inside has
814    /// actually been changed, it just means a mutable reference was
815    /// acquired after the last call to [`has_changed`].
816    ///
817    /// Some types like [`Text`], and traits like [`Widget`] offer
818    /// [`needs_update`] methods, you should try to determine what
819    /// parts to look for changes.
820    ///
821    /// Generally though, you can use this method to gauge that.
822    ///
823    /// [`write`]: RwData::write
824    /// [`write_as`]: RwData::write_as
825    /// [`read`]: RwData::read
826    /// [`has_changed`]: RwData::has_changed
827    /// [`Text`]: crate::text::Text
828    /// [`Widget`]: crate::ui::Widget
829    /// [`needs_update`]: crate::ui::Widget::needs_update
830    pub fn has_changed(&self) -> bool {
831        self.widget.has_changed() || self.area.has_changed()
832    }
833
834    /// Wether the [`RwData`] within and another point to the same
835    /// value
836    pub fn ptr_eq<T: ?Sized>(&self, other: &RwData<T>) -> bool {
837        self.widget.ptr_eq(other)
838    }
839
840    /// The [`Widget`]'s [`PrintCfg`]
841    pub fn cfg(&self, pa: &Pass) -> PrintCfg {
842        self.widget.read(pa, Widget::print_cfg)
843    }
844
845    /// Attaches a [`Searcher`] to this [`Handle`], so you can do
846    /// incremental search
847    ///
848    /// An [`Handle`] with a [`Searcher`] not only has its usual
849    /// editing capabilities, but is also able to act on requested
850    /// regex searches, like those from [`IncSearch`], in
851    /// [`duat-utils`]. This means that a user can type up a
852    /// [prompt] to search for something, and the [`Handle`]
853    /// can use the [`Searcher`] to interpret how that search will
854    /// be utilized. Examples of this can be found in the
855    /// [`duat-utils`] crate, as well as the [`duat-kak`] crate,
856    /// which has some more advanced usage.
857    ///
858    /// [`Searcher`]: crate::text::Searcher
859    /// [`Selection`]: crate::mode::Selection
860    /// [`Cursor`]: crate::mode::Cursor
861    /// [`IncSearch`]: https://docs.rs/duat-utils/latest/duat_utils/modes/struct.IncSearch.html
862    /// [`duat-utils`]: https://docs.rs/duat-utils/lastest/
863    /// [prompt]: https://docs.rs/duat-utils/latest/duat_utils/modes/trait.PromptMode.html
864    /// [`duat-kak`]: https://docs.rs/duat-kak/lastest/
865    pub fn attach_searcher(&self, searcher: Searcher) -> Handle<W, U, Searcher> {
866        Handle {
867            widget: self.widget.clone(),
868            area: self.area.clone(),
869            mask: self.mask.clone(),
870            searcher: RefCell::new(searcher),
871        }
872    }
873}
874
875impl<W: Widget<U> + ?Sized, U: Ui, S: Clone> Clone for Handle<W, U, S> {
876    fn clone(&self) -> Self {
877        Self {
878            widget: self.widget.clone(),
879            area: self.area.clone(),
880            mask: self.mask.clone(),
881            searcher: self.searcher.clone(),
882        }
883    }
884}