Selection mapping over changesets.

This commit is contained in:
Blaž Hrastnik 2020-05-28 14:59:50 +09:00
parent e52e848fd7
commit 1984410ac9
3 changed files with 37 additions and 2 deletions

View file

@ -13,4 +13,4 @@ pub use selection::Selection;
pub use state::State; pub use state::State;
pub use transaction::{Change, ChangeSet, Transaction}; pub use transaction::{Assoc, Change, ChangeSet, Transaction};

View file

@ -2,6 +2,7 @@
//! single selection range. //! single selection range.
//! //!
//! All positioning is done via `char` offsets into the buffer. //! All positioning is done via `char` offsets into the buffer.
use crate::{Assoc, ChangeSet};
use smallvec::{smallvec, SmallVec}; use smallvec::{smallvec, SmallVec};
#[inline] #[inline]
@ -59,7 +60,18 @@ impl Range {
} }
} }
// TODO: map /// Map a range through a set of changes. Returns a new range representing the same position
/// after the changes are applied.
pub fn map(self, changes: &ChangeSet) -> Self {
let anchor = changes.map_pos(self.anchor, Assoc::Before);
let head = changes.map_pos(self.head, Assoc::Before);
// TODO: possibly unnecessary
if self.anchor == anchor && self.head == head {
return self;
}
Self { anchor, head }
}
/// Extend the range to cover at least `from` `to`. /// Extend the range to cover at least `from` `to`.
#[must_use] #[must_use]
@ -115,6 +127,22 @@ impl Selection {
// add_range // push // add_range // push
// replace_range // replace_range
/// Map selections over a set of changes. Useful for adjusting the selection position after
/// applying changes to a document.
pub fn map(self, changes: &ChangeSet) -> Self {
if changes.is_empty() {
return self;
}
Self::new(
self.ranges
.into_iter()
.map(|range| range.map(changes))
.collect(),
self.primary_index,
)
}
#[must_use] #[must_use]
/// Constructs a selection holding a single range. /// Constructs a selection holding a single range.
pub fn single(anchor: usize, head: usize) -> Self { pub fn single(anchor: usize, head: usize) -> Self {

View file

@ -242,6 +242,13 @@ impl ChangeSet {
} }
} }
/// `true` when the set is empty.
#[inline]
pub fn is_empty(&self) -> bool {
let len = self.changes.len();
len == 0 || (len == 1 && self.changes[0] == Change::Retain(self.len))
}
/// Map a position through the changes. /// Map a position through the changes.
/// ///
/// `assoc` indicates which size to associate the position with. `Before` will keep the /// `assoc` indicates which size to associate the position with. `Before` will keep the