955 lines · 31.5 KB · Rust
RawDownload
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.