selection.rs

  1use crate::Anchor;
  2use crate::{rope::TextDimension, BufferSnapshot};
  3use std::cmp::Ordering;
  4
  5#[derive(Copy, Clone, Debug, Eq, PartialEq)]
  6pub enum SelectionGoal {
  7    None,
  8    Column(u32),
  9    ColumnRange { start: u32, end: u32 },
 10}
 11
 12#[derive(Clone, Debug, Eq, PartialEq)]
 13pub struct Selection<T> {
 14    pub id: usize,
 15    pub start: T,
 16    pub end: T,
 17    pub reversed: bool,
 18    pub goal: SelectionGoal,
 19}
 20
 21impl Default for SelectionGoal {
 22    fn default() -> Self {
 23        Self::None
 24    }
 25}
 26
 27impl<T: Clone> Selection<T> {
 28    pub fn head(&self) -> T {
 29        if self.reversed {
 30            self.start.clone()
 31        } else {
 32            self.end.clone()
 33        }
 34    }
 35
 36    pub fn tail(&self) -> T {
 37        if self.reversed {
 38            self.end.clone()
 39        } else {
 40            self.start.clone()
 41        }
 42    }
 43
 44    pub fn map<F, S>(&self, f: F) -> Selection<S>
 45    where
 46        F: Fn(T) -> S,
 47    {
 48        Selection::<S> {
 49            id: self.id,
 50            start: f(self.start.clone()),
 51            end: f(self.end.clone()),
 52            reversed: self.reversed,
 53            goal: self.goal,
 54        }
 55    }
 56}
 57
 58impl<T: Copy + Ord> Selection<T> {
 59    pub fn is_empty(&self) -> bool {
 60        self.start == self.end
 61    }
 62
 63    pub fn set_head(&mut self, head: T, new_goal: SelectionGoal) {
 64        if head.cmp(&self.tail()) < Ordering::Equal {
 65            if !self.reversed {
 66                self.end = self.start;
 67                self.reversed = true;
 68            }
 69            self.start = head;
 70        } else {
 71            if self.reversed {
 72                self.start = self.end;
 73                self.reversed = false;
 74            }
 75            self.end = head;
 76        }
 77        self.goal = new_goal;
 78    }
 79
 80    pub fn collapse_to(&mut self, point: T, new_goal: SelectionGoal) {
 81        self.start = point;
 82        self.end = point;
 83        self.goal = new_goal;
 84        self.reversed = false;
 85    }
 86}
 87
 88impl Selection<usize> {
 89    #[cfg(feature = "test-support")]
 90    pub fn from_offset(offset: usize) -> Self {
 91        Selection {
 92            id: 0,
 93            start: offset,
 94            end: offset,
 95            goal: SelectionGoal::None,
 96            reversed: false,
 97        }
 98    }
 99}
100
101impl Selection<Anchor> {
102    pub fn resolve<'a, D: 'a + TextDimension>(
103        &'a self,
104        snapshot: &'a BufferSnapshot,
105    ) -> Selection<D> {
106        Selection {
107            id: self.id,
108            start: snapshot.summary_for_anchor(&self.start),
109            end: snapshot.summary_for_anchor(&self.end),
110            reversed: self.reversed,
111            goal: self.goal,
112        }
113    }
114}