pub struct Handle<W: Widget<U> + ?Sized, U: Ui, S = ()> { /* private fields */ }Expand description
A handle to a Widget in Duat
The Handle lets you do all sorts of edits on a Widget. You
can, for example, make use of the Selections in its Text
in order to edit the Text in a very declarative way.
One of the places where this is commonly done is within Modes,
where you get access to the Handle of the currently active
Widget. Below is a very straightforward Mode:
use duat_core::prelude::*;
/// A very basic example Mode.
#[derive(Clone)]
struct PlacesCharactersAndMoves;
impl<U: Ui> Mode<U> for PlacesCharactersAndMoves {
type Widget = File<U>;
// ...
fn send_key(&mut self, _: &mut Pass, _: KeyEvent, _: Handle<Self::Widget, U>) {
todo!();
}
}In order to modify the widget, you must implement the
Mode::send_key method. In it, you receive the following:
- A
&mut Pass, which will give you access to all of duat’s shared state; - The key that was sent, may be a mapped key.
- The
Handlefor aMode::Widget.
use duat_core::prelude::*;
#[derive(Clone)]
struct PlacesCharactersAndMoves;
impl<U: Ui> Mode<U> for PlacesCharactersAndMoves {
type Widget = File<U>;
fn send_key(&mut self, pa: &mut Pass, key: KeyEvent, handle: Handle<File<U>, U>) {
match key {
// actions based on the key pressed
key!(KeyCode::Char('c')) => {
// Do something when the character 'c' is typed.
}
_ => todo!("The remaining keys"),
}
}
}(You can use the key! macro in order to match KeyEvents).
With the Handle, you can modify Text in a simplified
way. This is done by two actions, editing and moving. You
can only do one of these on any number of selections at the same
time.
impl<U: Ui> Mode<U> for PlacesCharactersAndMoves {
/* ... */
fn send_key(&mut self, pa: &mut Pass, key: KeyEvent, handle: Handle<Self::Widget, U>) {
match key {
key!(KeyCode::Char(c)) => {
handle.edit_all(pa, |mut e| {
e.insert('c');
e.move_hor(1);
});
},
key!(KeyCode::Right, KeyMod::SHIFT) => {
handle.edit_all(pa, |mut e| {
if e.anchor().is_none() {
e.set_anchor();
}
e.move_hor(1);
});
}
key!(KeyCode::Right) => {
handle.edit_all(pa, |mut e| {
e.unset_anchor();
e.move_hor(1);
});
}
_ => todo!("Predictable remaining implementations")
}
}Implementations§
Source§impl<W: Widget<U> + ?Sized, U: Ui, S> Handle<W, U, S>
impl<W: Widget<U> + ?Sized, U: Ui, S> Handle<W, U, S>
Sourcepub fn read<Ret>(&self, pa: &Pass, f: impl FnOnce(&W, &U::Area) -> Ret) -> Ret
pub fn read<Ret>(&self, pa: &Pass, f: impl FnOnce(&W, &U::Area) -> Ret) -> Ret
Reads from the Widget and the Area using a Pass
The consistent use of a Pass for the purposes of
reading/writing to the values of RwDatas ensures that no
panic or invalid borrow happens at runtime, even while working
with untrusted code. More importantly, Duat uses these
guarantees in order to give the end user a ridiculous amount
of freedom in where they can do things, whilst keeping Rust’s
number one rule and ensuring thread safety, even with a
relatively large amount of shareable state.
§Panics
Panics if there is a mutable borrow of this struct somewhere,
which could happen if you use RwData::write_unsafe or
RwData::write_unsafe_as from some other place
Sourcepub fn write<Ret>(
&self,
pa: &mut Pass,
f: impl FnOnce(&mut W, &U::Area) -> Ret,
) -> Ret
pub fn write<Ret>( &self, pa: &mut Pass, f: impl FnOnce(&mut W, &U::Area) -> Ret, ) -> Ret
Writes to the Widget and Area within using a Pass
The consistent use of a Pass for the purposes of
reading/writing to the values of RwDatas ensures that no
panic or invalid borrow happens at runtime, even while working
with untrusted code. More importantly, Duat uses these
guarantees in order to give the end user a ridiculous amount
of freedom in where they can do things, whilst keeping Rust’s
number one rule and ensuring thread safety, even with a
relatively large amount of shareable state.
§Panics
Panics if there is any type of borrow of this struct
somewhere, which could happen if you use
RwData::read_unsafe or RwData::write_unsafe, for
example.
Sourcepub fn edit_nth<Ret>(
&self,
pa: &mut Pass,
n: usize,
edit: impl FnOnce(Cursor<'_, W, U::Area, S>) -> Ret,
) -> Ret
pub fn edit_nth<Ret>( &self, pa: &mut Pass, n: usize, edit: impl FnOnce(Cursor<'_, W, U::Area, S>) -> Ret, ) -> Ret
Edits the nth Selection in the Text
Once dropped, the Selection in this Cursor will be
added back to the list of Selections, unless it is
destroyed
If you want to edit on the main selection, see edit_main,
if you want to edit on many Selections, see
edit_iter.
Just like all other edit methods, this one will populate the
Selections, so if there are no Selections, it will
create one at Point::default.
Sourcepub fn edit_main<Ret>(
&self,
pa: &mut Pass,
edit: impl FnOnce(Cursor<'_, W, U::Area, S>) -> Ret,
) -> Ret
pub fn edit_main<Ret>( &self, pa: &mut Pass, edit: impl FnOnce(Cursor<'_, W, U::Area, S>) -> Ret, ) -> Ret
Edits the main Selection in the Text
Once dropped, the Selection in this Cursor will be
added back to the list of Selections, unless it is
destroyed
If you want to edit on the nth selection, see edit_nth,
same for edit_last, if you want to edit on many
Selections, see edit_iter.
Just like all other edit methods, this one will populate the
Selections, so if there are no Selections, it will
create one at Point::default.
Sourcepub fn edit_last<Ret>(
&self,
pa: &mut Pass,
edit: impl FnOnce(Cursor<'_, W, U::Area, S>) -> Ret,
) -> Ret
pub fn edit_last<Ret>( &self, pa: &mut Pass, edit: impl FnOnce(Cursor<'_, W, U::Area, S>) -> Ret, ) -> Ret
Edits the last Selection in the Text
Once dropped, the Selection in this Cursor will be
added back to the list of Selections, unless it is
destroyed
If you want to edit on the nth selection, see edit_nth,
same for edit_main, if you want to edit on many
Selections, see edit_iter.
Just like all other edit methods, this one will populate the
Selections, so if there are no Selections, it will
create one at Point::default.
Sourcepub fn edit_iter<Ret>(
&self,
pa: &mut Pass,
edit: impl FnOnce(Cursors<'_, W, U::Area, S>) -> Ret,
) -> Ret
pub fn edit_iter<Ret>( &self, pa: &mut Pass, edit: impl FnOnce(Cursors<'_, W, U::Area, S>) -> Ret, ) -> Ret
A Lender over all Cursors of the Text
This lets you easily iterate over all Selections, without
having to worry about insertion affecting the order at which
they are edited (like what repeated calls to edit_nth
would do)
Note however that you can’t use a Lender (also known as a
lending iterator) in a for loop, but you should be able
to just while let Some(e) = editors.next() {} or
handle.edit_iter().for_each(|_| {}) instead.
Just like all other edit methods, this one will populate the
Selections, so if there are no Selections, it will
create one at Point::default.
Sourcepub fn edit_all(
&self,
pa: &mut Pass,
edit: impl FnMut(Cursor<'_, W, U::Area, S>),
)
pub fn edit_all( &self, pa: &mut Pass, edit: impl FnMut(Cursor<'_, W, U::Area, S>), )
A shortcut for iterating over all selections
This is the equivalent of calling:
handle.edit_iter(pa, |iter| iter.for_each(|e| { /* .. */ }));But it can’t return a value, and is meant to reduce the indentation that will inevitably come from using the equivalent long form call.
Sourcepub fn write_text<Ret>(
&self,
pa: &mut Pass,
write: impl FnOnce(&mut Text) -> Ret,
) -> Ret
pub fn write_text<Ret>( &self, pa: &mut Pass, write: impl FnOnce(&mut Text) -> Ret, ) -> Ret
Sourcepub fn read_selections<Ret>(
&self,
pa: &Pass,
read: impl FnOnce(&Selections) -> Ret,
) -> Ret
pub fn read_selections<Ret>( &self, pa: &Pass, read: impl FnOnce(&Selections) -> Ret, ) -> Ret
Reads the Selections of the Widget
Sourcepub fn write_selections<Ret>(
&self,
pa: &mut Pass,
write: impl FnOnce(&mut Selections) -> Ret,
) -> Ret
pub fn write_selections<Ret>( &self, pa: &mut Pass, write: impl FnOnce(&mut Selections) -> Ret, ) -> Ret
Writes to the Selections of the Widget
Sourcepub fn clone_text(&self, pa: &Pass) -> Text
pub fn clone_text(&self, pa: &Pass) -> Text
Clones the Text within
Sourcepub fn new_moment(&self, pa: &mut Pass)
pub fn new_moment(&self, pa: &mut Pass)
Finishes the current moment and adds a new one to the history
Sourcepub fn scroll_ver(&self, pa: &Pass, dist: i32)
pub fn scroll_ver(&self, pa: &Pass, dist: i32)
Scrolls the Text veritcally by an amount
If PrintCfg.allow_overscroll is set, then the Text
will be allowed to scroll beyond the last line, up until
reaching the scrolloff.y value.
Sourcepub fn scroll_to_points(&self, pa: &Pass, points: impl TwoPoints)
pub fn scroll_to_points(&self, pa: &Pass, points: impl TwoPoints)
Sourcepub fn start_points(&self, pa: &Pass) -> (Point, Option<Point>)
pub fn start_points(&self, pa: &Pass) -> (Point, Option<Point>)
The start points that should be printed
Sourcepub fn end_points(&self, pa: &Pass) -> (Point, Option<Point>)
pub fn end_points(&self, pa: &Pass) -> (Point, Option<Point>)
The end points that should be printed
Sourcepub fn mask(&self) -> &Rc<Cell<&'static str>>
pub fn mask(&self) -> &Rc<Cell<&'static str>>
Gets this Handle’s mask
This mask is going to be used to map Forms to other
Forms when printing via Widget::print. To see more
about how masks work, see form::enable_mask.
Sourcepub fn set_mask(&self, mask: &'static str) -> &'static str
pub fn set_mask(&self, mask: &'static str) -> &'static str
Sets this Handle’s mask, returning the previous one
This mask is going to be used to map Forms to other
Forms when printing via Widget::print. To see more
about how masks work, see form::enable_mask.
Sourcepub fn has_changed(&self) -> bool
pub fn has_changed(&self) -> bool
Wether someone else called write or write_as since the
last read or write
Do note that this DOES NOT mean that the value inside has
actually been changed, it just means a mutable reference was
acquired after the last call to has_changed.
Some types like Text, and traits like Widget offer
needs_update methods, you should try to determine what
parts to look for changes.
Generally though, you can use this method to gauge that.
Sourcepub fn ptr_eq<T: ?Sized>(&self, other: &RwData<T>) -> bool
pub fn ptr_eq<T: ?Sized>(&self, other: &RwData<T>) -> bool
Wether the RwData within and another point to the same
value
Sourcepub fn attach_searcher(&self, searcher: Searcher) -> Handle<W, U, Searcher>
pub fn attach_searcher(&self, searcher: Searcher) -> Handle<W, U, Searcher>
Attaches a Searcher to this Handle, so you can do
incremental search
An Handle with a Searcher not only has its usual
editing capabilities, but is also able to act on requested
regex searches, like those from IncSearch, in
duat-utils. This means that a user can type up a
prompt to search for something, and the Handle
can use the Searcher to interpret how that search will
be utilized. Examples of this can be found in the
duat-utils crate, as well as the duat-kak crate,
which has some more advanced usage.