pub struct Handle<W: Widget + ?Sized = Buffer, 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::prelude::*;
/// A very basic example Mode.
#[derive(Clone)]
struct PlacesCharactersAndMoves;
impl Mode for PlacesCharactersAndMoves {
type Widget = Buffer;
// ..
fn send_key(&mut self, _: &mut Pass, _: KeyEvent, _: Handle) {
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::prelude::*;
#[derive(Clone)]
struct PlacesCharactersAndMoves;
impl Mode for PlacesCharactersAndMoves {
type Widget = Buffer;
fn send_key(&mut self, pa: &mut Pass, key_event: KeyEvent, handle: Handle) {
match key_event {
// actions based on the key pressed
event!(KeyCode::Char(char)) => {
// Do something when the character 'c' is typed.
}
_ => todo!("The remaining keys"),
}
}
}Note the event! macro. It (alongside alt!, ctrl! and
shift!) can be used to easily create KeyEvents for
matching purposes. They are very useful for succinctly describing
an exact match in just a short pattern:
use KeyCode::*;
use duat::prelude::*;
let key_event = KeyEvent::from(Char('a'));
match key_event {
event!('a' | 'b') => { /* .. */ }
shift!(Right | Left) => { /* .. */ }
ctrl!(alt!('d')) => { /* .. */ }
_ => { /* .. */ }
}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 Mode for PlacesCharactersAndMoves {
type Widget = Buffer;
// ..
fn send_key(&mut self, pa: &mut Pass, key_event: KeyEvent, handle: Handle) {
use KeyCode::*;
match key_event {
event!(Char(char)) => handle.edit_all(pa, |mut c| {
c.insert('c');
c.move_hor(1);
}),
shift!(Right) => handle.edit_all(pa, |mut c| {
if c.anchor().is_none() {
c.set_anchor();
}
c.move_hor(1);
}),
event!(KeyCode::Right) => handle.edit_all(pa, |mut c| {
c.unset_anchor();
c.move_hor(1);
}),
_ => todo!("Predictable remaining implementations"),
}
}Implementations§
Source§impl<W: Widget + ?Sized, S> Handle<W, S>
impl<W: Widget + ?Sized, S> Handle<W, S>
Sourcepub fn read<'a>(&'a self, pa: &'a Pass) -> &'a W
pub fn read<'a>(&'a self, pa: &'a Pass) -> &'a W
Reads from the Widget, making use of 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.
Sourcepub fn read_as<'a, W2: Widget>(&'a self, pa: &'a Pass) -> Option<&'a W2>
pub fn read_as<'a, W2: Widget>(&'a self, pa: &'a Pass) -> Option<&'a W2>
Tries to read as a concrete Widget implementor
Sourcepub fn declare_as_read(&self)
pub fn declare_as_read(&self)
Sourcepub fn write<'a>(&'a self, pa: &'a mut Pass) -> &'a mut W
pub fn write<'a>(&'a self, pa: &'a mut Pass) -> &'a mut W
Writes to the Widget, making use of 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.
Sourcepub fn write_with_area<'a>(
&'a self,
pa: &'a mut Pass,
) -> (&'a mut W, &'a mut Area)
pub fn write_with_area<'a>( &'a self, pa: &'a mut Pass, ) -> (&'a mut W, &'a mut Area)
Writes to the Widget and Area, making use of 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.
Sourcepub fn declare_written(&self)
pub fn declare_written(&self)
Sourcepub fn try_downcast<W2: Widget>(&self) -> Option<Handle<W2>>
pub fn try_downcast<W2: Widget>(&self) -> Option<Handle<W2>>
Tries to downcast from dyn Widget to a concrete Widget
Sourcepub fn text_parts<'a>(&'a self, pa: &'a mut Pass) -> TextParts<'a>
pub fn text_parts<'a>(&'a self, pa: &'a mut Pass) -> TextParts<'a>
Sourcepub fn selections<'a>(&'a self, pa: &'a Pass) -> &'a Selections
pub fn selections<'a>(&'a self, pa: &'a Pass) -> &'a Selections
A shared reference to the Selections of the Widget’s
Text
This is the same as calling handle.read(pa).selections().
Sourcepub fn selections_mut<'a>(&'a self, pa: &'a mut Pass) -> &'a mut Selections
pub fn selections_mut<'a>(&'a self, pa: &'a mut Pass) -> &'a mut Selections
A mutable reference to the Selections of the Widget’s
Text
This is the same as calling
handle.write(pa).selections_mut().
Sourcepub fn edit_nth<Ret>(
&self,
pa: &mut Pass,
n: usize,
edit: impl FnOnce(Cursor<'_, W, S>) -> Ret,
) -> Ret
pub fn edit_nth<Ret>( &self, pa: &mut Pass, n: usize, edit: impl FnOnce(Cursor<'_, W, 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, S>) -> Ret,
) -> Ret
pub fn edit_main<Ret>( &self, pa: &mut Pass, edit: impl FnOnce(Cursor<'_, W, 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, S>) -> Ret,
) -> Ret
pub fn edit_last<Ret>( &self, pa: &mut Pass, edit: impl FnOnce(Cursor<'_, W, 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, S>) -> Ret,
) -> Ret
pub fn edit_iter<Ret>( &self, pa: &mut Pass, edit: impl FnOnce(Cursors<'_, W, 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, S>))
pub fn edit_all(&self, pa: &mut Pass, edit: impl FnMut(Cursor<'_, W, 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 scroll_ver(&self, pa: &mut Pass, dist: i32)
pub fn scroll_ver(&self, pa: &mut Pass, dist: i32)
Scrolls the Text veritcally by an amount
If PrintOpts.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: &mut Pass, points: TwoPoints)
pub fn scroll_to_points(&self, pa: &mut Pass, points: TwoPoints)
Sourcepub fn start_points(&self, pa: &Pass) -> TwoPoints
pub fn start_points(&self, pa: &Pass) -> TwoPoints
The start points that should be printed
Sourcepub fn end_points(&self, pa: &Pass) -> TwoPoints
pub fn end_points(&self, pa: &Pass) -> TwoPoints
The end points that should be printed
Sourcepub fn mask(&self) -> &Arc<Mutex<&'static str>>
pub fn mask(&self) -> &Arc<Mutex<&'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, pa: &Pass) -> bool
pub fn has_changed(&self, pa: &Pass) -> 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 master(&self) -> Result<&Handle<dyn Widget>, Text>
pub fn master(&self) -> Result<&Handle<dyn Widget>, Text>
Returns the Handle this one was pushed to, if it was
pushed to another
Will return Some if this self was created by calling
Handle::push_outer_widget, Handle::push_inner_widget,
Handle::spawn_widget, or if the Widget was spawned
on the master’s Text
Sourcepub fn buffer(&self) -> Result<Handle, Text>
pub fn buffer(&self) -> Result<Handle, Text>
Returns the Handle<Buffer> this one was pushed to, if it
was pushed to one
Will return Some if this self was created by calling
Handle::push_outer_widget, Handle::push_inner_widget,
Handle::spawn_widget, or if the Widget was spawned
on the master’s Text
Reads related Widgets of type W2, as well as its
Area
This can also be done by calling Handle::get_related, and
Handle::read, but this function should generally be
faster, since there is no cloning of Arcs going on.
Gets related Handles of type Widget
If you are doing this just to read the Widget and
Area, consider using Handle::read_related.
Sourcepub fn attach_searcher(&self, searcher: Searcher) -> Handle<W, Searcher>
pub fn attach_searcher(&self, searcher: Searcher) -> Handle<W, 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. 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 crate, as well as the duat-kak crate,
which has some more advanced usage.
Sourcepub fn push_inner_widget<PW: Widget>(
&self,
pa: &mut Pass,
widget: PW,
specs: PushSpecs,
) -> Handle<PW>
pub fn push_inner_widget<PW: Widget>( &self, pa: &mut Pass, widget: PW, specs: PushSpecs, ) -> Handle<PW>
Pushes a Widget around this one
This Widget will be placed internally, i.e., around the
Area of self. This is in contrast to
Handle::push_outer_widget, which will push around the
“cluster master” of self.
A cluster master is the collection of every Widget that was
pushed around a central one with PushSpecs::cluster set to
true.
Both of these functions behave identically in the situation
where no other Widgets were pushed around self.
However, if, for example, a Widget was previously pushed
below self, when pushing to the left, the following would
happen:
╭────────────────╮ ╭─────┬──────────╮
│ │ │ │ │
│ self │ │ new │ self │
│ │ -> │ │ │
├────────────────┤ ├─────┴──────────┤
│ old │ │ old │
╰────────────────╯ ╰────────────────╯While in Handle::push_outer_widget, this happens instead:
╭────────────────╮ ╭─────┬──────────╮
│ │ │ │ │
│ self │ │ │ self │
│ │ -> │ new │ │
├────────────────┤ │ ├──────────┤
│ old │ │ │ old │
╰────────────────╯ ╰─────┴──────────╯Note that new was pushed around other clustered widgets in
the second case, not just around self.
Sourcepub fn push_outer_widget<PW: Widget>(
&self,
pa: &mut Pass,
widget: PW,
specs: PushSpecs,
) -> Handle<PW>
pub fn push_outer_widget<PW: Widget>( &self, pa: &mut Pass, widget: PW, specs: PushSpecs, ) -> Handle<PW>
Pushes a Widget around the “cluster master” of this one
A cluster master is the collection of every Widget that was
pushed around a central one with PushSpecs::cluster set to
true.
This Widget will be placed externally, i.e., around every
other Widget that was pushed around self. This is in
contrast to Handle::push_inner_widget, which will push
only around self.
Both of these functions behave identically in the situation
where no other Widgets were pushed around self.
However, if, for example, a Widget was previously pushed
to the left of self, when pushing to the left again, the
following would happen:
╭──────┬──────────╮ ╭─────┬─────┬──────╮
│ │ │ │ │ │ │
│ │ │ │ │ │ │
│ old │ self │ -> │ new │ old │ self │
│ │ │ │ │ │ │
│ │ │ │ │ │ │
╰──────┴──────────╯ ╰─────┴─────┴──────╯While in Handle::push_inner_widget, this happens instead:
╭──────┬──────────╮ ╭─────┬─────┬──────╮
│ │ │ │ │ │ │
│ │ │ │ │ │ │
│ old │ self │ -> │ old │ new │ self │
│ │ │ │ │ │ │
│ │ │ │ │ │ │
╰──────┴──────────╯ ╰─────┴─────┴──────╯Note that new was pushed around other clustered widgets in
the first case, not just around self.
Sourcepub fn spawn_widget<SW: Widget>(
&self,
pa: &mut Pass,
widget: SW,
specs: SpawnSpecs,
) -> Option<Handle<SW>>
pub fn spawn_widget<SW: Widget>( &self, pa: &mut Pass, widget: SW, specs: SpawnSpecs, ) -> Option<Handle<SW>>
Spawns a floating Widget
Trait Implementations§
Source§impl<W: Widget + ?Sized> PushTarget for Handle<W>
impl<W: Widget + ?Sized> PushTarget for Handle<W>
impl<W: Widget + ?Sized, S> Send for Handle<W, S>
impl<W: Widget + ?Sized, S> Sync for Handle<W, S>
Auto Trait Implementations§
impl<W = Buffer, S = ()> !Freeze for Handle<W, S>
impl<W = Buffer, S = ()> !RefUnwindSafe for Handle<W, S>
impl<W, S> Unpin for Handle<W, S>
impl<W = Buffer, S = ()> !UnwindSafe for Handle<W, S>
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
Source§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>. Box<dyn Any> can
then be further downcast into Box<ConcreteType> where ConcreteType implements Trait.Source§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Rc<Trait> (where Trait: Downcast) to Rc<Any>. Rc<Any> can then be
further downcast into Rc<ConcreteType> where ConcreteType implements Trait.Source§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
&Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &Any’s vtable from &Trait’s.Source§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &mut Any’s vtable from &mut Trait’s.