use std::{ cell::Ref, cmp, iter, mem, ops::{Deref, DerefMut, Range, Sub}, sync::Arc,}; use collections::HashMap;use gpui::{App, Entity, Pixels};use itertools::Itertools;use language::{Bias, Point, Selection, SelectionGoal, TextDimension};use util::post_inc; use crate::{ Anchor, DisplayPoint, DisplayRow, ExcerptId, MultiBuffer, MultiBufferSnapshot, SelectMode, ToOffset, ToPoint, display_map::{DisplayMap, DisplaySnapshot, ToDisplayPoint}, movement::TextLayoutDetails,}; #[derive(Debug, Clone)]pub struct PendingSelection { pub selection: Selection<Anchor>, pub mode: SelectMode,} #[derive(Debug, Clone)]pub struct SelectionsCollection { display_map: Entity<DisplayMap>, buffer: Entity<MultiBuffer>, pub next_selection_id: usize, pub line_mode: bool, /// The non-pending, non-overlapping selections. /// The [SelectionsCollection::pending] selection could possibly overlap these pub disjoint: Arc<[Selection<Anchor>]>, /// A pending selection, such as when the mouse is being dragged pub pending: Option<PendingSelection>,} impl SelectionsCollection { pub fn new(display_map: Entity<DisplayMap>, buffer: Entity<MultiBuffer>) -> Self { Self { display_map, buffer, next_selection_id: 1, line_mode: false, disjoint: Arc::default(), pending: Some(PendingSelection { selection: Selection { id: 0, start: Anchor::min(), end: Anchor::min(), reversed: false, goal: SelectionGoal::None, }, mode: SelectMode::Character, }), } } pub fn display_map(&self, cx: &mut App) -> DisplaySnapshot { self.display_map.update(cx, |map, cx| map.snapshot(cx)) } fn buffer<'a>(&self, cx: &'a App) -> Ref<'a, MultiBufferSnapshot> { self.buffer.read(cx).read(cx) } pub fn clone_state(&mut self, other: &SelectionsCollection) { self.next_selection_id = other.next_selection_id; self.line_mode = other.line_mode; self.disjoint = other.disjoint.clone(); self.pending.clone_from(&other.pending); } pub fn count(&self) -> usize { let mut count = self.disjoint.len(); if self.pending.is_some() { count += 1; } count } /// The non-pending, non-overlapping selections. There could still be a pending /// selection that overlaps these if the mouse is being dragged, etc. Returned as /// selections over Anchors. pub fn disjoint_anchors(&self) -> Arc<[Selection<Anchor>]> { self.disjoint.clone() } pub fn disjoint_anchor_ranges(&self) -> impl Iterator<Item = Range<Anchor>> { // Mapping the Arc slice would borrow it, whereas indexing captures it. let disjoint = self.disjoint_anchors(); (0..disjoint.len()).map(move |ix| disjoint[ix].range()) } pub fn pending_anchor(&self) -> Option<Selection<Anchor>> { self.pending .as_ref() .map(|pending| pending.selection.clone()) } pub fn pending<D: TextDimension + Ord + Sub<D, Output = D>>( &self, cx: &mut App, ) -> Option<Selection<D>> { let map = self.display_map(cx); let selection = resolve_selections(self.pending_anchor().as_ref(), &map).next(); selection } pub(crate) fn pending_mode(&self) -> Option<SelectMode> { self.pending.as_ref().map(|pending| pending.mode.clone()) } pub fn all<'a, D>(&self, cx: &mut App) -> Vec<Selection<D>> where D: 'a + TextDimension + Ord + Sub<D, Output = D>, { let map = self.display_map(cx); let disjoint_anchors = &self.disjoint; let mut disjoint = resolve_selections::<D, _>(disjoint_anchors.iter(), &map).peekable(); let mut pending_opt = self.pending::<D>(cx); iter::from_fn(move || { if let Some(pending) = pending_opt.as_mut() { while let Some(next_selection) = disjoint.peek() { if pending.start <= next_selection.end && pending.end >= next_selection.start { let next_selection = disjoint.next().unwrap(); if next_selection.start < pending.start { pending.start = next_selection.start; } if next_selection.end > pending.end { pending.end = next_selection.end; } } else if next_selection.end < pending.start { return disjoint.next(); } else { break; } } pending_opt.take() } else { disjoint.next() } }) .collect() } /// Returns all of the selections, adjusted to take into account the selection line_mode pub fn all_adjusted(&self, cx: &mut App) -> Vec<Selection<Point>> { let mut selections = self.all::<Point>(cx); if self.line_mode { let map = self.display_map(cx); for selection in &mut selections { let new_range = map.expand_to_line(selection.range()); selection.start = new_range.start; selection.end = new_range.end; } } selections } /// Returns the newest selection, adjusted to take into account the selection line_mode pub fn newest_adjusted(&self, cx: &mut App) -> Selection<Point> { let mut selection = self.newest::<Point>(cx); if self.line_mode { let map = self.display_map(cx); let new_range = map.expand_to_line(selection.range()); selection.start = new_range.start; selection.end = new_range.end; } selection } pub fn all_adjusted_display( &self, cx: &mut App, ) -> (DisplaySnapshot, Vec<Selection<DisplayPoint>>) { if self.line_mode { let selections = self.all::<Point>(cx); let map = self.display_map(cx); let result = selections .into_iter() .map(|mut selection| { let new_range = map.expand_to_line(selection.range()); selection.start = new_range.start; selection.end = new_range.end; selection.map(|point| point.to_display_point(&map)) }) .collect(); (map, result) } else { self.all_display(cx) } } pub fn disjoint_in_range<'a, D>(&self, range: Range<Anchor>, cx: &mut App) -> Vec<Selection<D>> where D: 'a + TextDimension + Ord + Sub<D, Output = D> + std::fmt::Debug, { let map = self.display_map(cx); let start_ix = match self .disjoint .binary_search_by(|probe| probe.end.cmp(&range.start, &map.buffer_snapshot)) { Ok(ix) | Err(ix) => ix, }; let end_ix = match self .disjoint .binary_search_by(|probe| probe.start.cmp(&range.end, &map.buffer_snapshot)) { Ok(ix) => ix + 1, Err(ix) => ix, }; resolve_selections(&self.disjoint[start_ix..end_ix], &map).collect() } pub fn all_display(&self, cx: &mut App) -> (DisplaySnapshot, Vec<Selection<DisplayPoint>>) { let map = self.display_map(cx); let disjoint_anchors = &self.disjoint; let mut disjoint = resolve_selections_display(disjoint_anchors.iter(), &map).peekable(); let mut pending_opt = resolve_selections_display(self.pending_anchor().as_ref(), &map).next(); let selections = iter::from_fn(move || { if let Some(pending) = pending_opt.as_mut() { while let Some(next_selection) = disjoint.peek() { if pending.start <= next_selection.end && pending.end >= next_selection.start { let next_selection = disjoint.next().unwrap(); if next_selection.start < pending.start { pending.start = next_selection.start; } if next_selection.end > pending.end { pending.end = next_selection.end; } } else if next_selection.end < pending.start { return disjoint.next(); } else { break; } } pending_opt.take() } else { disjoint.next() } }) .collect(); (map, selections) } pub fn newest_anchor(&self) -> &Selection<Anchor> { self.pending .as_ref() .map(|s| &s.selection) .or_else(|| self.disjoint.iter().max_by_key(|s| s.id)) .unwrap() } pub fn newest<D: TextDimension + Ord + Sub<D, Output = D>>( &self, cx: &mut App, ) -> Selection<D> { let map = self.display_map(cx); let selection = resolve_selections([self.newest_anchor()], &map) .next() .unwrap(); selection } pub fn newest_display(&self, cx: &mut App) -> Selection<DisplayPoint> { let map = self.display_map(cx); let selection = resolve_selections_display([self.newest_anchor()], &map) .next() .unwrap(); selection } pub fn oldest_anchor(&self) -> &Selection<Anchor> { self.disjoint .iter() .min_by_key(|s| s.id) .or_else(|| self.pending.as_ref().map(|p| &p.selection)) .unwrap() } pub fn oldest<D: TextDimension + Ord + Sub<D, Output = D>>( &self, cx: &mut App, ) -> Selection<D> { let map = self.display_map(cx); let selection = resolve_selections([self.oldest_anchor()], &map) .next() .unwrap(); selection } pub fn first_anchor(&self) -> Selection<Anchor> { self.pending .as_ref() .map(|pending| pending.selection.clone()) .unwrap_or_else(|| self.disjoint.first().cloned().unwrap()) } pub fn first<D: TextDimension + Ord + Sub<D, Output = D>>(&self, cx: &mut App) -> Selection<D> { self.all(cx).first().unwrap().clone() } pub fn last<D: TextDimension + Ord + Sub<D, Output = D>>(&self, cx: &mut App) -> Selection<D> { self.all(cx).last().unwrap().clone() } pub fn ranges<D: TextDimension + Ord + Sub<D, Output = D>>( &self, cx: &mut App, ) -> Vec<Range<D>> { self.all::<D>(cx) .iter() .map(|s| { if s.reversed { s.end..s.start } else { s.start..s.end } }) .collect() } #[cfg(any(test, feature = "test-support"))] pub fn display_ranges(&self, cx: &mut App) -> Vec<Range<DisplayPoint>> { let display_map = self.display_map(cx); self.disjoint_anchors() .iter() .chain(self.pending_anchor().as_ref()) .map(|s| { if s.reversed { s.end.to_display_point(&display_map)..s.start.to_display_point(&display_map) } else { s.start.to_display_point(&display_map)..s.end.to_display_point(&display_map) } }) .collect() } pub fn build_columnar_selection( &mut self, display_map: &DisplaySnapshot, row: DisplayRow, positions: &Range<Pixels>, reversed: bool, text_layout_details: &TextLayoutDetails, ) -> Option<Selection<Point>> { let is_empty = positions.start == positions.end; let line_len = display_map.line_len(row); let line = display_map.layout_row(row, text_layout_details); let start_col = line.closest_index_for_x(positions.start) as u32; let (start, end) = if is_empty { let point = DisplayPoint::new(row, std::cmp::min(start_col, line_len)); (point, point) } else { if start_col >= line_len { return None; } let start = DisplayPoint::new(row, start_col); let end_col = line.closest_index_for_x(positions.end) as u32; let end = DisplayPoint::new(row, end_col); (start, end) }; Some(Selection { id: post_inc(&mut self.next_selection_id), start: start.to_point(display_map), end: end.to_point(display_map), reversed, goal: SelectionGoal::HorizontalRange { start: positions.start.into(), end: positions.end.into(), }, }) } pub fn change_with<R>( &mut self, cx: &mut App, change: impl FnOnce(&mut MutableSelectionsCollection) -> R, ) -> (bool, R) { let mut mutable_collection = MutableSelectionsCollection { collection: self, selections_changed: false, cx, }; let result = change(&mut mutable_collection); assert!( !mutable_collection.disjoint.is_empty() || mutable_collection.pending.is_some(), "There must be at least one selection" ); (mutable_collection.selections_changed, result) }} pub struct MutableSelectionsCollection<'a> { collection: &'a mut SelectionsCollection, selections_changed: bool, cx: &'a mut App,} impl<'a> MutableSelectionsCollection<'a> { pub fn display_map(&mut self) -> DisplaySnapshot { self.collection.display_map(self.cx) } pub fn buffer(&self) -> Ref<MultiBufferSnapshot> { self.collection.buffer(self.cx) } pub fn clear_disjoint(&mut self) { self.collection.disjoint = Arc::default(); } pub fn delete(&mut self, selection_id: usize) { let mut changed = false; self.collection.disjoint = self .disjoint .iter() .filter(|selection| { let found = selection.id == selection_id; changed |= found; !found }) .cloned() .collect(); self.selections_changed |= changed; } pub fn clear_pending(&mut self) { if self.collection.pending.is_some() { self.collection.pending = None; self.selections_changed = true; } } pub(crate) fn set_pending_anchor_range(&mut self, range: Range<Anchor>, mode: SelectMode) { self.collection.pending = Some(PendingSelection { selection: Selection { id: post_inc(&mut self.collection.next_selection_id), start: range.start, end: range.end, reversed: false, goal: SelectionGoal::None, }, mode, }); self.selections_changed = true; } pub(crate) fn set_pending(&mut self, selection: Selection<Anchor>, mode: SelectMode) { self.collection.pending = Some(PendingSelection { selection, mode }); self.selections_changed = true; } pub fn try_cancel(&mut self) -> bool { if let Some(pending) = self.collection.pending.take() { if self.disjoint.is_empty() { self.collection.disjoint = Arc::from([pending.selection]); } self.selections_changed = true; return true; } let mut oldest = self.oldest_anchor().clone(); if self.count() > 1 { self.collection.disjoint = Arc::from([oldest]); self.selections_changed = true; return true; } if !oldest.start.cmp(&oldest.end, &self.buffer()).is_eq() { let head = oldest.head(); oldest.start = head; oldest.end = head; self.collection.disjoint = Arc::from([oldest]); self.selections_changed = true; return true; } false } pub fn insert_range<T>(&mut self, range: Range<T>) where T: 'a + ToOffset + ToPoint + TextDimension + Ord + Sub<T, Output = T> + std::marker::Copy, { let mut selections = self.collection.all(self.cx); let mut start = range.start.to_offset(&self.buffer()); let mut end = range.end.to_offset(&self.buffer()); let reversed = if start > end { mem::swap(&mut start, &mut end);Lines 1–500 of 955. Load more
use std::{ cell::Ref, cmp, iter, mem, ops::{Deref, DerefMut, Range, Sub}, sync::Arc, }; use collections::HashMap; use gpui::{App, Entity, Pixels}; use itertools::Itertools; use language::{Bias, Point, Selection, SelectionGoal, TextDimension}; use util::post_inc; use crate::{ Anchor, DisplayPoint, DisplayRow, ExcerptId, MultiBuffer, MultiBufferSnapshot, SelectMode, ToOffset, ToPoint, display_map::{DisplayMap, DisplaySnapshot, ToDisplayPoint}, movement::TextLayoutDetails, }; #[derive(Debug, Clone)] pub struct PendingSelection { pub selection: Selection<Anchor>, pub mode: SelectMode, } #[derive(Debug, Clone)] pub struct SelectionsCollection { display_map: Entity<DisplayMap>, buffer: Entity<MultiBuffer>, pub next_selection_id: usize, pub line_mode: bool, /// The non-pending, non-overlapping selections. /// The [SelectionsCollection::pending] selection could possibly overlap these pub disjoint: Arc<[Selection<Anchor>]>, /// A pending selection, such as when the mouse is being dragged pub pending: Option<PendingSelection>, } impl SelectionsCollection { pub fn new(display_map: Entity<DisplayMap>, buffer: Entity<MultiBuffer>) -> Self { Self { display_map, buffer, next_selection_id: 1, line_mode: false, disjoint: Arc::default(), pending: Some(PendingSelection { selection: Selection { id: 0, start: Anchor::min(), end: Anchor::min(), reversed: false, goal: SelectionGoal::None, }, mode: SelectMode::Character, }), } } pub fn display_map(&self, cx: &mut App) -> DisplaySnapshot { self.display_map.update(cx, |map, cx| map.snapshot(cx)) } fn buffer<'a>(&self, cx: &'a App) -> Ref<'a, MultiBufferSnapshot> { self.buffer.read(cx).read(cx) } pub fn clone_state(&mut self, other: &SelectionsCollection) { self.next_selection_id = other.next_selection_id; self.line_mode = other.line_mode; self.disjoint = other.disjoint.clone(); self.pending.clone_from(&other.pending); } pub fn count(&self) -> usize { let mut count = self.disjoint.len(); if self.pending.is_some() { count += 1; } count } /// The non-pending, non-overlapping selections. There could still be a pending /// selection that overlaps these if the mouse is being dragged, etc. Returned as /// selections over Anchors. pub fn disjoint_anchors(&self) -> Arc<[Selection<Anchor>]> { self.disjoint.clone() } pub fn disjoint_anchor_ranges(&self) -> impl Iterator<Item = Range<Anchor>> { // Mapping the Arc slice would borrow it, whereas indexing captures it. let disjoint = self.disjoint_anchors(); (0..disjoint.len()).map(move |ix| disjoint[ix].range()) } pub fn pending_anchor(&self) -> Option<Selection<Anchor>> { self.pending .as_ref() .map(|pending| pending.selection.clone()) } pub fn pending<D: TextDimension + Ord + Sub<D, Output = D>>( &self, cx: &mut App, ) -> Option<Selection<D>> { let map = self.display_map(cx); let selection = resolve_selections(self.pending_anchor().as_ref(), &map).next(); selection } pub(crate) fn pending_mode(&self) -> Option<SelectMode> { self.pending.as_ref().map(|pending| pending.mode.clone()) } pub fn all<'a, D>(&self, cx: &mut App) -> Vec<Selection<D>> where D: 'a + TextDimension + Ord + Sub<D, Output = D>, { let map = self.display_map(cx); let disjoint_anchors = &self.disjoint; let mut disjoint = resolve_selections::<D, _>(disjoint_anchors.iter(), &map).peekable(); let mut pending_opt = self.pending::<D>(cx); iter::from_fn(move || { if let Some(pending) = pending_opt.as_mut() { while let Some(next_selection) = disjoint.peek() { if pending.start <= next_selection.end && pending.end >= next_selection.start { let next_selection = disjoint.next().unwrap(); if next_selection.start < pending.start { pending.start = next_selection.start; } if next_selection.end > pending.end { pending.end = next_selection.end; } } else if next_selection.end < pending.start { return disjoint.next(); } else { break; } } pending_opt.take() } else { disjoint.next() } }) .collect() } /// Returns all of the selections, adjusted to take into account the selection line_mode pub fn all_adjusted(&self, cx: &mut App) -> Vec<Selection<Point>> { let mut selections = self.all::<Point>(cx); if self.line_mode { let map = self.display_map(cx); for selection in &mut selections { let new_range = map.expand_to_line(selection.range()); selection.start = new_range.start; selection.end = new_range.end; } } selections } /// Returns the newest selection, adjusted to take into account the selection line_mode pub fn newest_adjusted(&self, cx: &mut App) -> Selection<Point> { let mut selection = self.newest::<Point>(cx); if self.line_mode { let map = self.display_map(cx); let new_range = map.expand_to_line(selection.range()); selection.start = new_range.start; selection.end = new_range.end; } selection } pub fn all_adjusted_display( &self, cx: &mut App, ) -> (DisplaySnapshot, Vec<Selection<DisplayPoint>>) { if self.line_mode { let selections = self.all::<Point>(cx); let map = self.display_map(cx); let result = selections .into_iter() .map(|mut selection| { let new_range = map.expand_to_line(selection.range()); selection.start = new_range.start; selection.end = new_range.end; selection.map(|point| point.to_display_point(&map)) }) .collect(); (map, result) } else { self.all_display(cx) } } pub fn disjoint_in_range<'a, D>(&self, range: Range<Anchor>, cx: &mut App) -> Vec<Selection<D>> where D: 'a + TextDimension + Ord + Sub<D, Output = D> + std::fmt::Debug, { let map = self.display_map(cx); let start_ix = match self .disjoint .binary_search_by(|probe| probe.end.cmp(&range.start, &map.buffer_snapshot)) { Ok(ix) | Err(ix) => ix, }; let end_ix = match self .disjoint .binary_search_by(|probe| probe.start.cmp(&range.end, &map.buffer_snapshot)) { Ok(ix) => ix + 1, Err(ix) => ix, }; resolve_selections(&self.disjoint[start_ix..end_ix], &map).collect() } pub fn all_display(&self, cx: &mut App) -> (DisplaySnapshot, Vec<Selection<DisplayPoint>>) { let map = self.display_map(cx); let disjoint_anchors = &self.disjoint; let mut disjoint = resolve_selections_display(disjoint_anchors.iter(), &map).peekable(); let mut pending_opt = resolve_selections_display(self.pending_anchor().as_ref(), &map).next(); let selections = iter::from_fn(move || { if let Some(pending) = pending_opt.as_mut() { while let Some(next_selection) = disjoint.peek() { if pending.start <= next_selection.end && pending.end >= next_selection.start { let next_selection = disjoint.next().unwrap(); if next_selection.start < pending.start { pending.start = next_selection.start; } if next_selection.end > pending.end { pending.end = next_selection.end; } } else if next_selection.end < pending.start { return disjoint.next(); } else { break; } } pending_opt.take() } else { disjoint.next() } }) .collect(); (map, selections) } pub fn newest_anchor(&self) -> &Selection<Anchor> { self.pending .as_ref() .map(|s| &s.selection) .or_else(|| self.disjoint.iter().max_by_key(|s| s.id)) .unwrap() } pub fn newest<D: TextDimension + Ord + Sub<D, Output = D>>( &self, cx: &mut App, ) -> Selection<D> { let map = self.display_map(cx); let selection = resolve_selections([self.newest_anchor()], &map) .next() .unwrap(); selection } pub fn newest_display(&self, cx: &mut App) -> Selection<DisplayPoint> { let map = self.display_map(cx); let selection = resolve_selections_display([self.newest_anchor()], &map) .next() .unwrap(); selection } pub fn oldest_anchor(&self) -> &Selection<Anchor> { self.disjoint .iter() .min_by_key(|s| s.id) .or_else(|| self.pending.as_ref().map(|p| &p.selection)) .unwrap() } pub fn oldest<D: TextDimension + Ord + Sub<D, Output = D>>( &self, cx: &mut App, ) -> Selection<D> { let map = self.display_map(cx); let selection = resolve_selections([self.oldest_anchor()], &map) .next() .unwrap(); selection } pub fn first_anchor(&self) -> Selection<Anchor> { self.pending .as_ref() .map(|pending| pending.selection.clone()) .unwrap_or_else(|| self.disjoint.first().cloned().unwrap()) } pub fn first<D: TextDimension + Ord + Sub<D, Output = D>>(&self, cx: &mut App) -> Selection<D> { self.all(cx).first().unwrap().clone() } pub fn last<D: TextDimension + Ord + Sub<D, Output = D>>(&self, cx: &mut App) -> Selection<D> { self.all(cx).last().unwrap().clone() } pub fn ranges<D: TextDimension + Ord + Sub<D, Output = D>>( &self, cx: &mut App, ) -> Vec<Range<D>> { self.all::<D>(cx) .iter() .map(|s| { if s.reversed { s.end..s.start } else { s.start..s.end } }) .collect() } #[cfg(any(test, feature = "test-support"))] pub fn display_ranges(&self, cx: &mut App) -> Vec<Range<DisplayPoint>> { let display_map = self.display_map(cx); self.disjoint_anchors() .iter() .chain(self.pending_anchor().as_ref()) .map(|s| { if s.reversed { s.end.to_display_point(&display_map)..s.start.to_display_point(&display_map) } else { s.start.to_display_point(&display_map)..s.end.to_display_point(&display_map) } }) .collect() } pub fn build_columnar_selection( &mut self, display_map: &DisplaySnapshot, row: DisplayRow, positions: &Range<Pixels>, reversed: bool, text_layout_details: &TextLayoutDetails, ) -> Option<Selection<Point>> { let is_empty = positions.start == positions.end; let line_len = display_map.line_len(row); let line = display_map.layout_row(row, text_layout_details); let start_col = line.closest_index_for_x(positions.start) as u32; let (start, end) = if is_empty { let point = DisplayPoint::new(row, std::cmp::min(start_col, line_len)); (point, point) } else { if start_col >= line_len { return None; } let start = DisplayPoint::new(row, start_col); let end_col = line.closest_index_for_x(positions.end) as u32; let end = DisplayPoint::new(row, end_col); (start, end) }; Some(Selection { id: post_inc(&mut self.next_selection_id), start: start.to_point(display_map), end: end.to_point(display_map), reversed, goal: SelectionGoal::HorizontalRange { start: positions.start.into(), end: positions.end.into(), }, }) } pub fn change_with<R>( &mut self, cx: &mut App, change: impl FnOnce(&mut MutableSelectionsCollection) -> R, ) -> (bool, R) { let mut mutable_collection = MutableSelectionsCollection { collection: self, selections_changed: false, cx, }; let result = change(&mut mutable_collection); assert!( !mutable_collection.disjoint.is_empty() || mutable_collection.pending.is_some(), "There must be at least one selection" ); (mutable_collection.selections_changed, result) } } pub struct MutableSelectionsCollection<'a> { collection: &'a mut SelectionsCollection, selections_changed: bool, cx: &'a mut App, } impl<'a> MutableSelectionsCollection<'a> { pub fn display_map(&mut self) -> DisplaySnapshot { self.collection.display_map(self.cx) } pub fn buffer(&self) -> Ref<MultiBufferSnapshot> { self.collection.buffer(self.cx) } pub fn clear_disjoint(&mut self) { self.collection.disjoint = Arc::default(); } pub fn delete(&mut self, selection_id: usize) { let mut changed = false; self.collection.disjoint = self .disjoint .iter() .filter(|selection| { let found = selection.id == selection_id; changed |= found; !found }) .cloned() .collect(); self.selections_changed |= changed; } pub fn clear_pending(&mut self) { if self.collection.pending.is_some() { self.collection.pending = None; self.selections_changed = true; } } pub(crate) fn set_pending_anchor_range(&mut self, range: Range<Anchor>, mode: SelectMode) { self.collection.pending = Some(PendingSelection { selection: Selection { id: post_inc(&mut self.collection.next_selection_id), start: range.start, end: range.end, reversed: false, goal: SelectionGoal::None, }, mode, }); self.selections_changed = true; } pub(crate) fn set_pending(&mut self, selection: Selection<Anchor>, mode: SelectMode) { self.collection.pending = Some(PendingSelection { selection, mode }); self.selections_changed = true; } pub fn try_cancel(&mut self) -> bool { if let Some(pending) = self.collection.pending.take() { if self.disjoint.is_empty() { self.collection.disjoint = Arc::from([pending.selection]); } self.selections_changed = true; return true; } let mut oldest = self.oldest_anchor().clone(); if self.count() > 1 { self.collection.disjoint = Arc::from([oldest]); self.selections_changed = true; return true; } if !oldest.start.cmp(&oldest.end, &self.buffer()).is_eq() { let head = oldest.head(); oldest.start = head; oldest.end = head; self.collection.disjoint = Arc::from([oldest]); self.selections_changed = true; return true; } false } pub fn insert_range<T>(&mut self, range: Range<T>) where T: 'a + ToOffset + ToPoint + TextDimension + Ord + Sub<T, Output = T> + std::marker::Copy, { let mut selections = self.collection.all(self.cx); let mut start = range.start.to_offset(&self.buffer()); let mut end = range.end.to_offset(&self.buffer()); let reversed = if start > end { mem::swap(&mut start, &mut end);