pub struct Cursor<'a, W: Widget + ?Sized = Buffer, S = ()> { /* private fields */ }Expand description
A selection that can edit Text, but can’t alter selections
This struct will be used only inside functions passed to the
edit_* family of methods from the Handle.
To make edits, you can use three different functions. You can,
those being replace, insert, and append. replace
will completely replace the Selection’s selection. insert
will place text behind the caret, and append will place it
after the caret.
You can also move the Selection’s selection in many different
ways, which are described below, in the impl section for this
struct.
let sel: String = handle.edit_main(&mut pa, |mut c| {
c.set_anchor();
c.set_caret_on_end();
c.replace("my replacement");
c.append(" and my edit");
c.swap_ends();
c.insert("This is ");
c.swap_ends();
c.move_hor(" and my edit".chars().count() as i32);
c.set_anchor();
c.move_hor(-("This is my replacement and my edit".chars().count() as i32));
c.selection().into_iter().collect()
});
assert_eq!(&sel, "This is my replacement and my edit");Implementations§
Source§impl<'a, W: Widget + ?Sized, S> Cursor<'a, W, S>
impl<'a, W: Widget + ?Sized, S> Cursor<'a, W, S>
Sourcepub fn replace(&mut self, edit: impl ToString)
pub fn replace(&mut self, edit: impl ToString)
Replaces the entire selection with new text
If there is a selection, then it is treated as inclusive,
therefore, a selection where caret == anchor will remove the
character where the caret is. If there is no selection, then
this has the same effect as insert. If you wish to
append to the caret instead, see append.
After replacing the sele tion, if the caret is behind the
anchor (or in the same spot), it will be placed on the start
of the selection, while the anchor will be placed on the
new end. If it is ahead, it will be placed ahead.
Sourcepub fn move_hor(&mut self, count: i32) -> i32
pub fn move_hor(&mut self, count: i32) -> i32
Moves the selection horizontally. May cause vertical movement
Returns the distance moved in chars.
Sourcepub fn move_ver(&mut self, count: i32) -> i32
pub fn move_ver(&mut self, count: i32) -> i32
Moves the selection vertically. May cause horizontal movement
Returns the distance moved in lines.
Sourcepub fn move_ver_wrapped(&mut self, count: i32)
pub fn move_ver_wrapped(&mut self, count: i32)
Moves the selection vertically a number of wrapped lines. May cause horizontal movement
Returns the distance moved in wrapped lines.
Sourcepub fn move_to(&mut self, point_or_points: impl CaretOrRange)
pub fn move_to(&mut self, point_or_points: impl CaretOrRange)
Moves the selection to a Point or a range of Points
If you give it just a Point, it will move the caret,
without affecting the anchor. If you give it a range of
Points, the anchor will be placed at the start, while the
caret will be placed at the end of said range. You can flip
those positions with a function like swap_ends.
If a Point is not valid, it will be corrected and clamped
to the lenght of the Text.
Sourcepub fn move_to_start(&mut self)
pub fn move_to_start(&mut self)
Moves the selection to Point::default, i.c., the start of
the Text
Sourcepub fn move_to_coords(&mut self, line: usize, col: usize)
pub fn move_to_coords(&mut self, line: usize, col: usize)
Moves the selection to a line and a column
- If the coords isn’t valid, it will move to the “maximum” position allowed.
Sourcepub fn move_to_col(&mut self, col: usize)
pub fn move_to_col(&mut self, col: usize)
Moves to a column on the current line
Sourcepub fn unset_anchor(&mut self) -> Option<Point>
pub fn unset_anchor(&mut self) -> Option<Point>
Returns and takes the anchor of the Selection.
Sourcepub fn set_anchor(&mut self)
pub fn set_anchor(&mut self)
Sets the anchor to the current caret
Sourcepub fn set_anchor_if_needed(&mut self) -> bool
pub fn set_anchor_if_needed(&mut self) -> bool
Sets the anchor if it was not already set
Returns true if the anchor was set by this command.
Sourcepub fn set_caret_on_start(&mut self) -> bool
pub fn set_caret_on_start(&mut self) -> bool
Sets the caret of the Selection on the start of the
selection
Returns true if a swap occurred
Sourcepub fn set_caret_on_end(&mut self) -> bool
pub fn set_caret_on_end(&mut self) -> bool
Sets the caret of the Selection on the end of the
selection
Returns true if a swap occurred
Sourcepub fn copy(&mut self) -> Cursor<'_, W, S>
pub fn copy(&mut self) -> Cursor<'_, W, S>
Copies the current Selection in place
This will leave an additional Selection with the current
selection. Do note that normal intersection rules apply, so if
at the end of the movement, this selection intersects with any
other, they will be merged into one.
When this Cursor is dropped, like with normal Cursors,
its Selection will be added to the Selections, unless
you destroy it.
Sourcepub fn set_desired_vcol(&mut self, x: usize)
pub fn set_desired_vcol(&mut self, x: usize)
Sets the “desired visual column”
The desired visual column determines at what point in a line the caret will be placed when moving up and down through lines of varying lengths.
Will also set the “desired wrapped visual column”, which is the same thing but used when moving vertically in a wrapped fashion.
Sourcepub fn matches<R: RegexPattern>(&self, pat: R) -> bool
pub fn matches<R: RegexPattern>(&self, pat: R) -> bool
Wether the current selection matches a regex pattern
Sourcepub fn search_fwd<R: RegexPattern>(
&self,
pat: R,
) -> impl Iterator<Item = R::Match> + '_
pub fn search_fwd<R: RegexPattern>( &self, pat: R, ) -> impl Iterator<Item = R::Match> + '_
Searches the Text for a regex
The search will begin on the caret and returns the
Range<usize> for the match, where the bounding usizes
represents a byte index, and can be directly used in, for
example, Cursor::move_to.
fn search_nth(pa: &mut Pass, handle: &Handle, n: usize, pat: &str) {
handle.edit_all(pa, |mut c| {
let mut nth = c.search_fwd(pat).nth(n);
if let Some(range) = nth {
c.move_to(range);
}
})
}§Panics
If the regex is not valid, this method will panic.
Sourcepub fn search_fwd_until<R: RegexPattern>(
&self,
pat: R,
until: impl TextIndex,
) -> impl Iterator<Item = R::Match> + '_
pub fn search_fwd_until<R: RegexPattern>( &self, pat: R, until: impl TextIndex, ) -> impl Iterator<Item = R::Match> + '_
Searches the Text for a regex, with an upper limit
The search will begin on the caret and returns the
Range<usize> for the match, where the bounding usizes
represents a byte index, and can be directly used in, for
example, Cursor::move_to.
fn find_within(pa: &mut Pass, handle: &Handle, pat: &str) {
handle.edit_all(pa, |mut c| {
c.set_caret_on_start();
let mut range = c.search_fwd_until(pat, c.range().end).next();
if let Some(range) = range {
c.move_to(range);
}
})
}§Panics
If the regex is not valid, this method will panic.
Sourcepub fn search_fwd_excl<R: RegexPattern>(
&self,
pat: R,
) -> impl Iterator<Item = R::Match> + '_
pub fn search_fwd_excl<R: RegexPattern>( &self, pat: R, ) -> impl Iterator<Item = R::Match> + '_
Searches the Text for a regex, skipping the caret’s
character
The search will begin one character afer the caret and
returns the Range<usize> for the match, where the
bounding usizes represents a byte index, and can be
directly used in, for example, Cursor::move_to.
fn next_paren_match(pa: &mut Pass, handle: &Handle) {
handle.edit_all(pa, |mut c| {
let mut start_count = 0;
let mut start_bound = None;
let end_bound = c.search_fwd_excl([r"\(", r"\)"]).find(|(id, range)| {
start_count += ((*id == 0) as u32).saturating_sub((*id == 1) as u32);
start_bound = (*id == 0 && start_count == 0).then_some(range.clone());
start_count == 0 && *id == 1
});
if let (Some(start), Some((_, end))) = (start_bound, end_bound) {
c.move_to(start.start..end.end);
}
})
}§Panics
If the regex is not valid, this method will panic.
Sourcepub fn search_fwd_excl_until<R: RegexPattern>(
&self,
pat: R,
until: impl TextIndex,
) -> impl Iterator<Item = R::Match> + '_
pub fn search_fwd_excl_until<R: RegexPattern>( &self, pat: R, until: impl TextIndex, ) -> impl Iterator<Item = R::Match> + '_
Searches the Text for a regex, with an upper limit and
skipping the caret’s character
The search will begin one character afer the caret and
returns the Range<usize> for the match, where the
bounding usizes represents a byte index, and can be
directly used in, for example, Cursor::move_to.
#[derive(Clone, Copy)]
enum Action {
Move,
Select,
Delete,
Change,
}
fn f_key_from_vim(pa: &mut Pass, handle: &Handle, char: char, n: usize, action: Action) {
handle.edit_all(pa, |mut c| {
let line_end = c.search_fwd('\n').next().unwrap();
let mut nth = c.search_fwd_excl_until(char, line_end.start).nth(n);
match (nth, action) {
(Some(range), Action::Move) => {
c.unset_anchor();
c.move_to(range.start);
}
(Some(range), Action::Select) => {
c.set_anchor_if_needed();
c.move_to(range.start);
}
(Some(range), Action::Delete | Action::Change) => {
c.set_anchor_if_needed();
c.move_to(range.start);
c.replace("");
}
_ => {}
}
});
if let Action::Change = action {
mode::set(Insert);
}
}§Panics
If the regex is not valid, this method will panic.
Sourcepub fn search_rev<R: RegexPattern>(
&self,
pat: R,
) -> impl Iterator<Item = R::Match> + '_
pub fn search_rev<R: RegexPattern>( &self, pat: R, ) -> impl Iterator<Item = R::Match> + '_
Searches the Text for a regex, in reverse
The search will begin on the caret and returns the
Range<usize> for the match, where the bounding usizes
represents a byte index, and can be directly used in, for
example, Cursor::move_to.
fn remove_prefix(pa: &mut Pass, handle: &Handle) {
let prefix_pat = format!(r"{}*\z", handle.opts(pa).word_chars_regex());
handle.edit_all(pa, |mut c| {
let prefix_range = c.search_rev(&prefix_pat).next();
if let Some(range) = prefix_range {
c.move_to(range);
c.replace("");
}
})
}§Panics
If the regex is not valid, this method will panic.
Sourcepub fn search_rev_until<R: RegexPattern>(
&self,
pat: R,
until: impl TextIndex,
) -> impl Iterator<Item = R::Match> + '_
pub fn search_rev_until<R: RegexPattern>( &self, pat: R, until: impl TextIndex, ) -> impl Iterator<Item = R::Match> + '_
Searches the Text for a regex, in reverse, until a given
point
The search will begin on the caret and returns the
Range<usize> for the match, where the bounding usizes
represents a byte index, and can be directly used in, for
example, Cursor::move_to.
fn search_before_but_after_prev(pa: &mut Pass, handle: &Handle, pat: &str) {
let mut last_end = 0;
handle.edit_all(pa, |mut c| {
let mut nth = c.search_rev_until(pat, last_end).next();
if let Some(range) = nth {
c.move_to(range)
}
last_end = c.range().end.byte();
})
}§Panics
If the regex is not valid, this method will panic.
Sourcepub fn search_rev_incl<R: RegexPattern>(
&self,
pat: R,
) -> impl Iterator<Item = R::Match> + '_
pub fn search_rev_incl<R: RegexPattern>( &self, pat: R, ) -> impl Iterator<Item = R::Match> + '_
Searches the Text for a regex, in reverse, including the
caret’s character
The search will begin on the character right after the caret
and returns the Range<usize> for the match, where the
bounding usizes represents a byte index, and can be
directly used in, for example, Cursor::move_to.
fn last_word_in_selection(pa: &mut Pass, handle: &Handle) {
let word_pat = format!(r"{}+", handle.opts(pa).word_chars_regex());
handle.edit_all(pa, |mut c| {
c.set_caret_on_end();
let mut nth = c.search_rev_incl(&word_pat).next();
if let Some(range) = nth {
c.move_to(range)
} else {
c.reset()
}
})
}§Panics
If the regex is not valid, this method will panic.
Sourcepub fn search_rev_incl_until<R: RegexPattern>(
&self,
pat: R,
until: impl TextIndex,
) -> impl Iterator<Item = R::Match> + '_
pub fn search_rev_incl_until<R: RegexPattern>( &self, pat: R, until: impl TextIndex, ) -> impl Iterator<Item = R::Match> + '_
Searches the Text for a regex, in reverse, including the
caret’s character, until a given point
The search will begin on the character right after the caret
and returns the Range<usize> for the match, where the
bounding usizes represents a byte index, and can be
directly used in, for example, Cursor::move_to.
fn last_word_limited_to_selection(pa: &mut Pass, handle: &Handle) {
let word_pat = format!(r"{}+", handle.opts(pa).word_chars_regex());
handle.edit_all(pa, |mut c| {
c.set_caret_on_end();
let start = c.range().start;
let mut nth = c.search_rev_incl_until(&word_pat, start).next();
if let Some(range) = nth {
c.move_to(range)
} else {
c.reset()
}
})
}§Panics
If the regex is not valid, this method will panic.
Sourcepub fn selection(&self) -> Strs<'_> ⓘ
pub fn selection(&self) -> Strs<'_> ⓘ
Returns the Selection’s selection
The reason why this return value is IntoIter<&str, 2> is
because the Text utilizes an underlying GapBuffer
to store the characters. This means that the text is
always separated into two distinct chunks.
If this Selection’s selection happens to be entirely
within one of these chunks, the other &str will just be
empty.
Sourcepub fn last_point(&self) -> Point
pub fn last_point(&self) -> Point
Returns the position of the last char if there is one
Sourcepub fn range(&self) -> Range<Point>
pub fn range(&self) -> Range<Point>
The Point range of the Selection
This is an inclusive range (not Rust’s RangeInclusive
however), this means that, even if there is no anchor, the
lenght of this range will always be at least 1.
If you want an exclusive range, see Cursor::range_excl
Sourcepub fn range_excl(&self) -> Range<Point>
pub fn range_excl(&self) -> Range<Point>
An exclusive Point range of the Selection
If you wish for an inclusive range, whose length is always
greater than or equal to 1, see RangeInclusive.
Sourcepub fn anchor_is_start(&self) -> bool
pub fn anchor_is_start(&self) -> bool
Returns true if the anchor exists before the caret
Source§impl<W: Widget + ?Sized> Cursor<'_, W, Searcher>
Incremental search functions, only available on IncSearchers
impl<W: Widget + ?Sized> Cursor<'_, W, Searcher>
Incremental search functions, only available on IncSearchers
Trait Implementations§
Auto Trait Implementations§
impl<'a, W = Buffer, S = ()> !Freeze for Cursor<'a, W, S>
impl<'a, W = Buffer, S = ()> !RefUnwindSafe for Cursor<'a, W, S>
impl<'a, W = Buffer, S = ()> !Send for Cursor<'a, W, S>
impl<'a, W = Buffer, S = ()> !Sync for Cursor<'a, W, S>
impl<'a, W, S> Unpin for Cursor<'a, W, S>where
W: ?Sized,
impl<'a, W = Buffer, S = ()> !UnwindSafe for Cursor<'a, 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> 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.