selection.rs

  1use super::{AnchorRangeMap, Buffer, Content, Point, ToOffset, ToPoint};
  2use std::{cmp::Ordering, ops::Range, sync::Arc};
  3
  4pub type SelectionSetId = clock::Lamport;
  5pub type SelectionsVersion = usize;
  6
  7#[derive(Copy, Clone, Debug, Eq, PartialEq)]
  8pub enum SelectionGoal {
  9    None,
 10    Column(u32),
 11    ColumnRange { start: u32, end: u32 },
 12}
 13
 14#[derive(Clone, Debug, Eq, PartialEq)]
 15pub struct Selection<T> {
 16    pub id: usize,
 17    pub start: T,
 18    pub end: T,
 19    pub reversed: bool,
 20    pub goal: SelectionGoal,
 21}
 22
 23#[derive(Clone, Debug, Eq, PartialEq)]
 24pub struct SelectionSet {
 25    pub id: SelectionSetId,
 26    pub active: bool,
 27    pub selections: Arc<AnchorRangeMap<SelectionState>>,
 28}
 29
 30#[derive(Debug, Eq, PartialEq)]
 31pub struct SelectionState {
 32    pub id: usize,
 33    pub reversed: bool,
 34    pub goal: SelectionGoal,
 35}
 36
 37impl<T: ToOffset + ToPoint + Copy + Ord> Selection<T> {
 38    pub fn is_empty(&self) -> bool {
 39        self.start == self.end
 40    }
 41
 42    pub fn head(&self) -> T {
 43        if self.reversed {
 44            self.start
 45        } else {
 46            self.end
 47        }
 48    }
 49
 50    pub fn set_head(&mut self, head: T) {
 51        if head.cmp(&self.tail()) < Ordering::Equal {
 52            if !self.reversed {
 53                self.end = self.start;
 54                self.reversed = true;
 55            }
 56            self.start = head;
 57        } else {
 58            if self.reversed {
 59                self.start = self.end;
 60                self.reversed = false;
 61            }
 62            self.end = head;
 63        }
 64    }
 65
 66    pub fn tail(&self) -> T {
 67        if self.reversed {
 68            self.end
 69        } else {
 70            self.start
 71        }
 72    }
 73
 74    pub fn point_range(&self, buffer: &Buffer) -> Range<Point> {
 75        let start = self.start.to_point(buffer);
 76        let end = self.end.to_point(buffer);
 77        if self.reversed {
 78            end..start
 79        } else {
 80            start..end
 81        }
 82    }
 83
 84    pub fn offset_range(&self, buffer: &Buffer) -> Range<usize> {
 85        let start = self.start.to_offset(buffer);
 86        let end = self.end.to_offset(buffer);
 87        if self.reversed {
 88            end..start
 89        } else {
 90            start..end
 91        }
 92    }
 93}
 94
 95impl SelectionSet {
 96    pub fn len(&self) -> usize {
 97        self.selections.len()
 98    }
 99
100    pub fn offset_selections<'a>(
101        &'a self,
102        content: impl Into<Content<'a>> + 'a,
103    ) -> impl 'a + Iterator<Item = Selection<usize>> {
104        self.selections
105            .offset_ranges(content)
106            .map(|(range, state)| Selection {
107                id: state.id,
108                start: range.start,
109                end: range.end,
110                reversed: state.reversed,
111                goal: state.goal,
112            })
113    }
114
115    pub fn point_selections<'a>(
116        &'a self,
117        content: impl Into<Content<'a>> + 'a,
118    ) -> impl 'a + Iterator<Item = Selection<Point>> {
119        self.selections
120            .point_ranges(content)
121            .map(|(range, state)| Selection {
122                id: state.id,
123                start: range.start,
124                end: range.end,
125                reversed: state.reversed,
126                goal: state.goal,
127            })
128    }
129}