aboutsummaryrefslogtreecommitdiff
path: root/helix-core/src/selection.rs
diff options
context:
space:
mode:
Diffstat (limited to 'helix-core/src/selection.rs')
-rw-r--r--helix-core/src/selection.rs88
1 files changed, 47 insertions, 41 deletions
diff --git a/helix-core/src/selection.rs b/helix-core/src/selection.rs
index 064abec7..ca1a6d32 100644
--- a/helix-core/src/selection.rs
+++ b/helix-core/src/selection.rs
@@ -159,6 +159,12 @@ impl Selection {
}
}
+ pub fn add(mut self, range: Range) -> Self {
+ let index = self.ranges.len();
+ self.ranges.push(range);
+
+ Self::normalize(self.ranges, index)
+ }
// add_range // push
// replace_range
@@ -204,53 +210,53 @@ impl Selection {
Self::single(pos, pos)
}
- // TODO: consume an iterator or a vec to reduce allocations?
- #[must_use]
- pub fn new(ranges: SmallVec<[Range; 1]>, primary_index: usize) -> Self {
- assert!(!ranges.is_empty());
+ fn normalize(mut ranges: SmallVec<[Range; 1]>, mut primary_index: usize) -> Selection {
+ let primary = ranges[primary_index];
+ ranges.sort_unstable_by_key(Range::from);
+ primary_index = ranges.iter().position(|&range| range == primary).unwrap();
- fn normalize(mut ranges: SmallVec<[Range; 1]>, mut primary_index: usize) -> Selection {
- let primary = ranges[primary_index];
- ranges.sort_unstable_by_key(Range::from);
- primary_index = ranges.iter().position(|&range| range == primary).unwrap();
-
- let mut result = SmallVec::with_capacity(ranges.len()); // approx
-
- // TODO: we could do with one vec by removing elements as we mutate
-
- for (i, range) in ranges.into_iter().enumerate() {
- // if previous value exists
- if let Some(prev) = result.last_mut() {
- // and we overlap it
- if range.overlaps(prev) {
- let from = prev.from();
- let to = std::cmp::max(range.to(), prev.to());
-
- if i <= primary_index {
- primary_index -= 1
- }
-
- // merge into previous
- if range.anchor > range.head {
- prev.anchor = to;
- prev.head = from;
- } else {
- prev.anchor = from;
- prev.head = to;
- }
- continue;
+ let mut result = SmallVec::with_capacity(ranges.len()); // approx
+
+ // TODO: we could do with one vec by removing elements as we mutate
+
+ for (i, range) in ranges.into_iter().enumerate() {
+ // if previous value exists
+ if let Some(prev) = result.last_mut() {
+ // and we overlap it
+ if range.overlaps(prev) {
+ let from = prev.from();
+ let to = std::cmp::max(range.to(), prev.to());
+
+ if i <= primary_index {
+ primary_index -= 1
}
- }
- result.push(range)
+ // merge into previous
+ if range.anchor > range.head {
+ prev.anchor = to;
+ prev.head = from;
+ } else {
+ prev.anchor = from;
+ prev.head = to;
+ }
+ continue;
+ }
}
- Selection {
- ranges: result,
- primary_index,
- }
+ result.push(range)
}
+ Selection {
+ ranges: result,
+ primary_index,
+ }
+ }
+
+ // TODO: consume an iterator or a vec to reduce allocations?
+ #[must_use]
+ pub fn new(ranges: SmallVec<[Range; 1]>, primary_index: usize) -> Self {
+ assert!(!ranges.is_empty());
+
// fast path for a single selection (cursor)
if ranges.len() == 1 {
return Self {
@@ -260,7 +266,7 @@ impl Selection {
}
// TODO: only normalize if needed (any ranges out of order)
- normalize(ranges, primary_index)
+ Self::normalize(ranges, primary_index)
}
/// Takes a closure and maps each selection over the closure.