selection.rs

  1use crate::{
  2    editor::{
  3        buffer::{Anchor, Buffer, Point, ToOffset as _, ToPoint as _},
  4        Bias, DisplayMapSnapshot, DisplayPoint,
  5    },
  6    time,
  7};
  8use std::{cmp::Ordering, mem, ops::Range};
  9
 10pub type SelectionSetId = time::Lamport;
 11pub type SelectionsVersion = usize;
 12
 13#[derive(Copy, Clone, Debug, Eq, PartialEq)]
 14pub enum SelectionGoal {
 15    None,
 16    Column(u32),
 17    ColumnRange { start: u32, end: u32 },
 18}
 19
 20#[derive(Clone, Debug, Eq, PartialEq)]
 21pub struct Selection {
 22    pub id: usize,
 23    pub start: Anchor,
 24    pub end: Anchor,
 25    pub reversed: bool,
 26    pub goal: SelectionGoal,
 27}
 28
 29impl Selection {
 30    pub fn head(&self) -> &Anchor {
 31        if self.reversed {
 32            &self.start
 33        } else {
 34            &self.end
 35        }
 36    }
 37
 38    pub fn set_head(&mut self, buffer: &Buffer, cursor: Anchor) {
 39        if cursor.cmp(self.tail(), buffer).unwrap() < Ordering::Equal {
 40            if !self.reversed {
 41                mem::swap(&mut self.start, &mut self.end);
 42                self.reversed = true;
 43            }
 44            self.start = cursor;
 45        } else {
 46            if self.reversed {
 47                mem::swap(&mut self.start, &mut self.end);
 48                self.reversed = false;
 49            }
 50            self.end = cursor;
 51        }
 52    }
 53
 54    pub fn tail(&self) -> &Anchor {
 55        if self.reversed {
 56            &self.end
 57        } else {
 58            &self.start
 59        }
 60    }
 61
 62    pub fn point_range(&self, buffer: &Buffer) -> Range<Point> {
 63        let start = self.start.to_point(buffer);
 64        let end = self.end.to_point(buffer);
 65        if self.reversed {
 66            end..start
 67        } else {
 68            start..end
 69        }
 70    }
 71
 72    pub fn offset_range(&self, buffer: &Buffer) -> Range<usize> {
 73        let start = self.start.to_offset(buffer);
 74        let end = self.end.to_offset(buffer);
 75        if self.reversed {
 76            end..start
 77        } else {
 78            start..end
 79        }
 80    }
 81
 82    pub fn display_range(&self, map: &DisplayMapSnapshot) -> Range<DisplayPoint> {
 83        let start = self.start.to_display_point(map);
 84        let end = self.end.to_display_point(map);
 85        if self.reversed {
 86            end..start
 87        } else {
 88            start..end
 89        }
 90    }
 91
 92    pub fn buffer_rows_for_display_rows(
 93        &self,
 94        include_end_if_at_line_start: bool,
 95        map: &DisplayMapSnapshot,
 96    ) -> (Range<u32>, Range<u32>) {
 97        let display_start = self.start.to_display_point(map);
 98        let buffer_start =
 99            DisplayPoint::new(display_start.row(), 0).to_buffer_point(map, Bias::Left);
100
101        let mut display_end = self.end.to_display_point(map);
102        if !include_end_if_at_line_start
103            && display_end.row() != map.max_point().row()
104            && display_start.row() != display_end.row()
105            && display_end.column() == 0
106        {
107            *display_end.row_mut() -= 1;
108        }
109        let buffer_end = DisplayPoint::new(display_end.row(), map.line_len(display_end.row()))
110            .to_buffer_point(map, Bias::Left);
111
112        (
113            buffer_start.row..buffer_end.row + 1,
114            display_start.row()..display_end.row() + 1,
115        )
116    }
117}