selections_collection.rs

   1use std::{
   2    cmp, fmt, iter, mem,
   3    ops::{AddAssign, Deref, DerefMut, Range, Sub},
   4    sync::Arc,
   5};
   6
   7use collections::HashMap;
   8use gpui::Pixels;
   9use itertools::Itertools as _;
  10use language::{Bias, Point, Selection, SelectionGoal};
  11use multi_buffer::{MultiBufferDimension, MultiBufferOffset};
  12use util::post_inc;
  13
  14use crate::{
  15    Anchor, DisplayPoint, DisplayRow, ExcerptId, MultiBufferSnapshot, SelectMode, ToOffset,
  16    display_map::{DisplaySnapshot, ToDisplayPoint},
  17    movement::TextLayoutDetails,
  18};
  19
  20#[derive(Debug, Clone)]
  21pub struct PendingSelection {
  22    selection: Selection<Anchor>,
  23    mode: SelectMode,
  24}
  25
  26#[derive(Debug, Clone)]
  27pub struct SelectionsCollection {
  28    next_selection_id: usize,
  29    line_mode: bool,
  30    /// The non-pending, non-overlapping selections.
  31    /// The [SelectionsCollection::pending] selection could possibly overlap these
  32    disjoint: Arc<[Selection<Anchor>]>,
  33    /// A pending selection, such as when the mouse is being dragged
  34    pending: Option<PendingSelection>,
  35    select_mode: SelectMode,
  36    is_extending: bool,
  37}
  38
  39impl SelectionsCollection {
  40    pub fn new() -> Self {
  41        Self {
  42            next_selection_id: 1,
  43            line_mode: false,
  44            disjoint: Arc::default(),
  45            pending: Some(PendingSelection {
  46                selection: Selection {
  47                    id: 0,
  48                    start: Anchor::min(),
  49                    end: Anchor::min(),
  50                    reversed: false,
  51                    goal: SelectionGoal::None,
  52                },
  53                mode: SelectMode::Character,
  54            }),
  55            select_mode: SelectMode::Character,
  56            is_extending: false,
  57        }
  58    }
  59
  60    pub fn clone_state(&mut self, other: &SelectionsCollection) {
  61        self.next_selection_id = other.next_selection_id;
  62        self.line_mode = other.line_mode;
  63        self.disjoint = other.disjoint.clone();
  64        self.pending.clone_from(&other.pending);
  65    }
  66
  67    pub fn count(&self) -> usize {
  68        let mut count = self.disjoint.len();
  69        if self.pending.is_some() {
  70            count += 1;
  71        }
  72        count
  73    }
  74
  75    /// The non-pending, non-overlapping selections. There could be a pending selection that
  76    /// overlaps these if the mouse is being dragged, etc. This could also be empty if there is a
  77    /// pending selection. Returned as selections over Anchors.
  78    pub fn disjoint_anchors_arc(&self) -> Arc<[Selection<Anchor>]> {
  79        self.disjoint.clone()
  80    }
  81
  82    /// The non-pending, non-overlapping selections. There could be a pending selection that
  83    /// overlaps these if the mouse is being dragged, etc. This could also be empty if there is a
  84    /// pending selection. Returned as selections over Anchors.
  85    pub fn disjoint_anchors(&self) -> &[Selection<Anchor>] {
  86        &self.disjoint
  87    }
  88
  89    pub fn disjoint_anchor_ranges(&self) -> impl Iterator<Item = Range<Anchor>> {
  90        // Mapping the Arc slice would borrow it, whereas indexing captures it.
  91        let disjoint = self.disjoint_anchors_arc();
  92        (0..disjoint.len()).map(move |ix| disjoint[ix].range())
  93    }
  94
  95    /// Non-overlapping selections using anchors, including the pending selection.
  96    pub fn all_anchors(&self, snapshot: &DisplaySnapshot) -> Arc<[Selection<Anchor>]> {
  97        if self.pending.is_none() {
  98            self.disjoint_anchors_arc()
  99        } else {
 100            let all_offset_selections = self.all::<MultiBufferOffset>(snapshot);
 101            all_offset_selections
 102                .into_iter()
 103                .map(|selection| selection_to_anchor_selection(selection, snapshot))
 104                .collect()
 105        }
 106    }
 107
 108    pub fn pending_anchor(&self) -> Option<&Selection<Anchor>> {
 109        self.pending.as_ref().map(|pending| &pending.selection)
 110    }
 111
 112    pub fn pending_anchor_mut(&mut self) -> Option<&mut Selection<Anchor>> {
 113        self.pending.as_mut().map(|pending| &mut pending.selection)
 114    }
 115
 116    pub fn pending<D>(&self, snapshot: &DisplaySnapshot) -> Option<Selection<D>>
 117    where
 118        D: MultiBufferDimension + Sub + AddAssign<<D as Sub>::Output> + Ord,
 119    {
 120        resolve_selections_wrapping_blocks(self.pending_anchor(), &snapshot).next()
 121    }
 122
 123    pub(crate) fn pending_mode(&self) -> Option<SelectMode> {
 124        self.pending.as_ref().map(|pending| pending.mode.clone())
 125    }
 126
 127    pub fn all<D>(&self, snapshot: &DisplaySnapshot) -> Vec<Selection<D>>
 128    where
 129        D: MultiBufferDimension + Sub + AddAssign<<D as Sub>::Output> + Ord,
 130    {
 131        let disjoint_anchors = &self.disjoint;
 132        let mut disjoint =
 133            resolve_selections_wrapping_blocks::<D, _>(disjoint_anchors.iter(), &snapshot)
 134                .peekable();
 135        let mut pending_opt = self.pending::<D>(&snapshot);
 136        iter::from_fn(move || {
 137            if let Some(pending) = pending_opt.as_mut() {
 138                while let Some(next_selection) = disjoint.peek() {
 139                    if pending.start <= next_selection.end && pending.end >= next_selection.start {
 140                        let next_selection = disjoint.next().unwrap();
 141                        if next_selection.start < pending.start {
 142                            pending.start = next_selection.start;
 143                        }
 144                        if next_selection.end > pending.end {
 145                            pending.end = next_selection.end;
 146                        }
 147                    } else if next_selection.end < pending.start {
 148                        return disjoint.next();
 149                    } else {
 150                        break;
 151                    }
 152                }
 153
 154                pending_opt.take()
 155            } else {
 156                disjoint.next()
 157            }
 158        })
 159        .collect()
 160    }
 161
 162    /// Returns all of the selections, adjusted to take into account the selection line_mode
 163    pub fn all_adjusted(&self, snapshot: &DisplaySnapshot) -> Vec<Selection<Point>> {
 164        let mut selections = self.all::<Point>(&snapshot);
 165        if self.line_mode {
 166            for selection in &mut selections {
 167                let new_range = snapshot.expand_to_line(selection.range());
 168                selection.start = new_range.start;
 169                selection.end = new_range.end;
 170            }
 171        }
 172        selections
 173    }
 174
 175    /// Returns the newest selection, adjusted to take into account the selection line_mode
 176    pub fn newest_adjusted(&self, snapshot: &DisplaySnapshot) -> Selection<Point> {
 177        let mut selection = self.newest::<Point>(&snapshot);
 178        if self.line_mode {
 179            let new_range = snapshot.expand_to_line(selection.range());
 180            selection.start = new_range.start;
 181            selection.end = new_range.end;
 182        }
 183        selection
 184    }
 185
 186    pub fn all_adjusted_display(
 187        &self,
 188        display_map: &DisplaySnapshot,
 189    ) -> Vec<Selection<DisplayPoint>> {
 190        if self.line_mode {
 191            let selections = self.all::<Point>(&display_map);
 192            let result = selections
 193                .into_iter()
 194                .map(|mut selection| {
 195                    let new_range = display_map.expand_to_line(selection.range());
 196                    selection.start = new_range.start;
 197                    selection.end = new_range.end;
 198                    selection.map(|point| point.to_display_point(&display_map))
 199                })
 200                .collect();
 201            result
 202        } else {
 203            self.all_display(display_map)
 204        }
 205    }
 206
 207    pub fn disjoint_in_range<D>(
 208        &self,
 209        range: Range<Anchor>,
 210        snapshot: &DisplaySnapshot,
 211    ) -> Vec<Selection<D>>
 212    where
 213        D: MultiBufferDimension + Sub + AddAssign<<D as Sub>::Output> + Ord + std::fmt::Debug,
 214    {
 215        let start_ix = match self
 216            .disjoint
 217            .binary_search_by(|probe| probe.end.cmp(&range.start, snapshot.buffer_snapshot()))
 218        {
 219            Ok(ix) | Err(ix) => ix,
 220        };
 221        let end_ix = match self
 222            .disjoint
 223            .binary_search_by(|probe| probe.start.cmp(&range.end, snapshot.buffer_snapshot()))
 224        {
 225            Ok(ix) => ix + 1,
 226            Err(ix) => ix,
 227        };
 228        resolve_selections_wrapping_blocks(&self.disjoint[start_ix..end_ix], snapshot).collect()
 229    }
 230
 231    pub fn all_display(&self, snapshot: &DisplaySnapshot) -> Vec<Selection<DisplayPoint>> {
 232        let disjoint_anchors = &self.disjoint;
 233        let mut disjoint =
 234            resolve_selections_display(disjoint_anchors.iter(), &snapshot).peekable();
 235        let mut pending_opt = resolve_selections_display(self.pending_anchor(), &snapshot).next();
 236        iter::from_fn(move || {
 237            if let Some(pending) = pending_opt.as_mut() {
 238                while let Some(next_selection) = disjoint.peek() {
 239                    if pending.start <= next_selection.end && pending.end >= next_selection.start {
 240                        let next_selection = disjoint.next().unwrap();
 241                        if next_selection.start < pending.start {
 242                            pending.start = next_selection.start;
 243                        }
 244                        if next_selection.end > pending.end {
 245                            pending.end = next_selection.end;
 246                        }
 247                    } else if next_selection.end < pending.start {
 248                        return disjoint.next();
 249                    } else {
 250                        break;
 251                    }
 252                }
 253
 254                pending_opt.take()
 255            } else {
 256                disjoint.next()
 257            }
 258        })
 259        .collect()
 260    }
 261
 262    pub fn newest_anchor(&self) -> &Selection<Anchor> {
 263        self.pending
 264            .as_ref()
 265            .map(|s| &s.selection)
 266            .or_else(|| self.disjoint.iter().max_by_key(|s| s.id))
 267            .unwrap()
 268    }
 269
 270    pub fn newest<D>(&self, snapshot: &DisplaySnapshot) -> Selection<D>
 271    where
 272        D: MultiBufferDimension + Sub + AddAssign<<D as Sub>::Output> + Ord,
 273    {
 274        resolve_selections_wrapping_blocks([self.newest_anchor()], &snapshot)
 275            .next()
 276            .unwrap()
 277    }
 278
 279    pub fn newest_display(&self, snapshot: &DisplaySnapshot) -> Selection<DisplayPoint> {
 280        resolve_selections_display([self.newest_anchor()], &snapshot)
 281            .next()
 282            .unwrap()
 283    }
 284
 285    pub fn oldest_anchor(&self) -> &Selection<Anchor> {
 286        self.disjoint
 287            .iter()
 288            .min_by_key(|s| s.id)
 289            .or_else(|| self.pending.as_ref().map(|p| &p.selection))
 290            .unwrap()
 291    }
 292
 293    pub fn oldest<D>(&self, snapshot: &DisplaySnapshot) -> Selection<D>
 294    where
 295        D: MultiBufferDimension + Sub + AddAssign<<D as Sub>::Output> + Ord,
 296    {
 297        resolve_selections_wrapping_blocks([self.oldest_anchor()], &snapshot)
 298            .next()
 299            .unwrap()
 300    }
 301
 302    pub fn first_anchor(&self) -> Selection<Anchor> {
 303        self.pending
 304            .as_ref()
 305            .map(|pending| pending.selection.clone())
 306            .unwrap_or_else(|| self.disjoint.first().cloned().unwrap())
 307    }
 308
 309    pub fn first<D>(&self, snapshot: &DisplaySnapshot) -> Selection<D>
 310    where
 311        D: MultiBufferDimension + Sub + AddAssign<<D as Sub>::Output> + Ord,
 312    {
 313        self.all(snapshot).first().unwrap().clone()
 314    }
 315
 316    pub fn last<D>(&self, snapshot: &DisplaySnapshot) -> Selection<D>
 317    where
 318        D: MultiBufferDimension + Sub + AddAssign<<D as Sub>::Output> + Ord,
 319    {
 320        self.all(snapshot).last().unwrap().clone()
 321    }
 322
 323    /// Returns a list of (potentially backwards!) ranges representing the selections.
 324    /// Useful for test assertions, but prefer `.all()` instead.
 325    #[cfg(any(test, feature = "test-support"))]
 326    pub fn ranges<D>(&self, snapshot: &DisplaySnapshot) -> Vec<Range<D>>
 327    where
 328        D: MultiBufferDimension + Sub + AddAssign<<D as Sub>::Output> + Ord,
 329    {
 330        self.all::<D>(snapshot)
 331            .iter()
 332            .map(|s| {
 333                if s.reversed {
 334                    s.end..s.start
 335                } else {
 336                    s.start..s.end
 337                }
 338            })
 339            .collect()
 340    }
 341
 342    #[cfg(any(test, feature = "test-support"))]
 343    pub fn display_ranges(&self, display_snapshot: &DisplaySnapshot) -> Vec<Range<DisplayPoint>> {
 344        self.disjoint_anchors_arc()
 345            .iter()
 346            .chain(self.pending_anchor())
 347            .map(|s| {
 348                if s.reversed {
 349                    s.end.to_display_point(display_snapshot)
 350                        ..s.start.to_display_point(display_snapshot)
 351                } else {
 352                    s.start.to_display_point(display_snapshot)
 353                        ..s.end.to_display_point(display_snapshot)
 354                }
 355            })
 356            .collect()
 357    }
 358
 359    /// Attempts to build a selection in the provided `DisplayRow` within the
 360    /// same range as the provided range of `Pixels`.
 361    /// Returns `None` if the range is not empty but it starts past the line's
 362    /// length, meaning that the line isn't long enough to be contained within
 363    /// part of the provided range.
 364    pub fn build_columnar_selection(
 365        &mut self,
 366        display_map: &DisplaySnapshot,
 367        row: DisplayRow,
 368        positions: &Range<Pixels>,
 369        reversed: bool,
 370        text_layout_details: &TextLayoutDetails,
 371    ) -> Option<Selection<Point>> {
 372        let is_empty = positions.start == positions.end;
 373        let line_len = display_map.line_len(row);
 374        let line = display_map.layout_row(row, text_layout_details);
 375        let start_col = line.closest_index_for_x(positions.start) as u32;
 376
 377        let (start, end) = if is_empty {
 378            let point = DisplayPoint::new(row, std::cmp::min(start_col, line_len));
 379            (point, point)
 380        } else {
 381            if start_col >= line_len {
 382                return None;
 383            }
 384            let start = DisplayPoint::new(row, start_col);
 385            let end_col = line.closest_index_for_x(positions.end) as u32;
 386            let end = DisplayPoint::new(row, end_col);
 387            (start, end)
 388        };
 389
 390        Some(Selection {
 391            id: post_inc(&mut self.next_selection_id),
 392            start: start.to_point(display_map),
 393            end: end.to_point(display_map),
 394            reversed,
 395            goal: SelectionGoal::HorizontalRange {
 396                start: positions.start.into(),
 397                end: positions.end.into(),
 398            },
 399        })
 400    }
 401
 402    pub fn change_with<R>(
 403        &mut self,
 404        snapshot: &DisplaySnapshot,
 405        change: impl FnOnce(&mut MutableSelectionsCollection<'_, '_>) -> R,
 406    ) -> (bool, R) {
 407        let mut mutable_collection = MutableSelectionsCollection {
 408            snapshot,
 409            collection: self,
 410            selections_changed: false,
 411        };
 412
 413        let result = change(&mut mutable_collection);
 414        assert!(
 415            !mutable_collection.disjoint.is_empty() || mutable_collection.pending.is_some(),
 416            "There must be at least one selection"
 417        );
 418        if cfg!(debug_assertions) {
 419            mutable_collection.disjoint.iter().for_each(|selection| {
 420                assert!(
 421                    snapshot.can_resolve(&selection.start),
 422                    "disjoint selection start is not resolvable for the given snapshot:\n{selection:?}, {excerpt:?}",
 423                    excerpt = snapshot.buffer_for_excerpt(selection.start.excerpt_id).map(|snapshot| snapshot.remote_id()),
 424                );
 425                assert!(
 426                    snapshot.can_resolve(&selection.end),
 427                    "disjoint selection end is not resolvable for the given snapshot: {selection:?}, {excerpt:?}",
 428                    excerpt = snapshot.buffer_for_excerpt(selection.end.excerpt_id).map(|snapshot| snapshot.remote_id()),
 429                );
 430            });
 431            if let Some(pending) = &mutable_collection.pending {
 432                let selection = &pending.selection;
 433                assert!(
 434                    snapshot.can_resolve(&selection.start),
 435                    "pending selection start is not resolvable for the given snapshot: {pending:?}, {excerpt:?}",
 436                    excerpt = snapshot
 437                        .buffer_for_excerpt(selection.start.excerpt_id)
 438                        .map(|snapshot| snapshot.remote_id()),
 439                );
 440                assert!(
 441                    snapshot.can_resolve(&selection.end),
 442                    "pending selection end is not resolvable for the given snapshot: {pending:?}, {excerpt:?}",
 443                    excerpt = snapshot
 444                        .buffer_for_excerpt(selection.end.excerpt_id)
 445                        .map(|snapshot| snapshot.remote_id()),
 446                );
 447            }
 448        }
 449        (mutable_collection.selections_changed, result)
 450    }
 451
 452    pub fn next_selection_id(&self) -> usize {
 453        self.next_selection_id
 454    }
 455
 456    pub fn line_mode(&self) -> bool {
 457        self.line_mode
 458    }
 459
 460    pub fn set_line_mode(&mut self, line_mode: bool) {
 461        self.line_mode = line_mode;
 462    }
 463
 464    pub fn select_mode(&self) -> &SelectMode {
 465        &self.select_mode
 466    }
 467
 468    pub fn set_select_mode(&mut self, select_mode: SelectMode) {
 469        self.select_mode = select_mode;
 470    }
 471
 472    pub fn is_extending(&self) -> bool {
 473        self.is_extending
 474    }
 475
 476    pub fn set_is_extending(&mut self, is_extending: bool) {
 477        self.is_extending = is_extending;
 478    }
 479}
 480
 481pub struct MutableSelectionsCollection<'snap, 'a> {
 482    collection: &'a mut SelectionsCollection,
 483    snapshot: &'snap DisplaySnapshot,
 484    selections_changed: bool,
 485}
 486
 487impl<'snap, 'a> fmt::Debug for MutableSelectionsCollection<'snap, 'a> {
 488    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 489        f.debug_struct("MutableSelectionsCollection")
 490            .field("collection", &self.collection)
 491            .field("selections_changed", &self.selections_changed)
 492            .finish()
 493    }
 494}
 495
 496impl<'snap, 'a> MutableSelectionsCollection<'snap, 'a> {
 497    pub fn display_snapshot(&self) -> DisplaySnapshot {
 498        self.snapshot.clone()
 499    }
 500
 501    pub fn clear_disjoint(&mut self) {
 502        self.collection.disjoint = Arc::default();
 503    }
 504
 505    pub fn delete(&mut self, selection_id: usize) {
 506        let mut changed = false;
 507        self.collection.disjoint = self
 508            .disjoint
 509            .iter()
 510            .filter(|selection| {
 511                let found = selection.id == selection_id;
 512                changed |= found;
 513                !found
 514            })
 515            .cloned()
 516            .collect();
 517
 518        self.selections_changed |= changed;
 519    }
 520
 521    pub fn remove_selections_from_buffer(&mut self, buffer_id: language::BufferId) {
 522        let mut changed = false;
 523
 524        let filtered_selections: Arc<[Selection<Anchor>]> = {
 525            self.disjoint
 526                .iter()
 527                .filter(|selection| {
 528                    if let Some(selection_buffer_id) =
 529                        self.snapshot.buffer_id_for_anchor(selection.start)
 530                    {
 531                        let should_remove = selection_buffer_id == buffer_id;
 532                        changed |= should_remove;
 533                        !should_remove
 534                    } else {
 535                        true
 536                    }
 537                })
 538                .cloned()
 539                .collect()
 540        };
 541
 542        if filtered_selections.is_empty() {
 543            let buffer_snapshot = self.snapshot.buffer_snapshot();
 544            let anchor = buffer_snapshot
 545                .excerpts()
 546                .find(|(_, buffer, _)| buffer.remote_id() == buffer_id)
 547                .and_then(|(excerpt_id, _, range)| {
 548                    buffer_snapshot.anchor_in_excerpt(excerpt_id, range.context.start)
 549                })
 550                .unwrap_or_else(|| self.snapshot.anchor_before(MultiBufferOffset(0)));
 551            self.collection.disjoint = Arc::from([Selection {
 552                id: post_inc(&mut self.collection.next_selection_id),
 553                start: anchor,
 554                end: anchor,
 555                reversed: false,
 556                goal: SelectionGoal::None,
 557            }]);
 558        } else {
 559            self.collection.disjoint = filtered_selections;
 560        }
 561
 562        self.selections_changed |= changed;
 563    }
 564
 565    pub fn clear_pending(&mut self) {
 566        if self.collection.pending.is_some() {
 567            self.collection.pending = None;
 568            self.selections_changed = true;
 569        }
 570    }
 571
 572    pub(crate) fn set_pending_anchor_range(&mut self, range: Range<Anchor>, mode: SelectMode) {
 573        self.collection.pending = Some(PendingSelection {
 574            selection: {
 575                let mut start = range.start;
 576                let mut end = range.end;
 577                let reversed = if start.cmp(&end, self.snapshot).is_gt() {
 578                    mem::swap(&mut start, &mut end);
 579                    true
 580                } else {
 581                    false
 582                };
 583                Selection {
 584                    id: post_inc(&mut self.collection.next_selection_id),
 585                    start,
 586                    end,
 587                    reversed,
 588                    goal: SelectionGoal::None,
 589                }
 590            },
 591            mode,
 592        });
 593        self.selections_changed = true;
 594    }
 595
 596    pub(crate) fn set_pending(&mut self, selection: Selection<Anchor>, mode: SelectMode) {
 597        self.collection.pending = Some(PendingSelection { selection, mode });
 598        self.selections_changed = true;
 599    }
 600
 601    pub fn try_cancel(&mut self) -> bool {
 602        if let Some(pending) = self.collection.pending.take() {
 603            if self.disjoint.is_empty() {
 604                self.collection.disjoint = Arc::from([pending.selection]);
 605            }
 606            self.selections_changed = true;
 607            return true;
 608        }
 609
 610        let mut oldest = self.oldest_anchor().clone();
 611        if self.count() > 1 {
 612            self.collection.disjoint = Arc::from([oldest]);
 613            self.selections_changed = true;
 614            return true;
 615        }
 616
 617        if !oldest.start.cmp(&oldest.end, self.snapshot).is_eq() {
 618            let head = oldest.head();
 619            oldest.start = head;
 620            oldest.end = head;
 621            self.collection.disjoint = Arc::from([oldest]);
 622            self.selections_changed = true;
 623            return true;
 624        }
 625
 626        false
 627    }
 628
 629    pub fn insert_range<T>(&mut self, range: Range<T>)
 630    where
 631        T: ToOffset,
 632    {
 633        let display_map = self.display_snapshot();
 634        let mut selections = self.collection.all(&display_map);
 635        let mut start = range.start.to_offset(self.snapshot);
 636        let mut end = range.end.to_offset(self.snapshot);
 637        let reversed = if start > end {
 638            mem::swap(&mut start, &mut end);
 639            true
 640        } else {
 641            false
 642        };
 643        selections.push(Selection {
 644            id: post_inc(&mut self.collection.next_selection_id),
 645            start,
 646            end,
 647            reversed,
 648            goal: SelectionGoal::None,
 649        });
 650        self.select(selections);
 651    }
 652
 653    pub fn select<T>(&mut self, selections: Vec<Selection<T>>)
 654    where
 655        T: ToOffset + std::marker::Copy + std::fmt::Debug,
 656    {
 657        let mut selections = selections
 658            .into_iter()
 659            .map(|selection| selection.map(|it| it.to_offset(self.snapshot)))
 660            .map(|mut selection| {
 661                if selection.start > selection.end {
 662                    mem::swap(&mut selection.start, &mut selection.end);
 663                    selection.reversed = true
 664                }
 665                selection
 666            })
 667            .collect::<Vec<_>>();
 668        selections.sort_unstable_by_key(|s| s.start);
 669        // Merge overlapping selections.
 670        let mut i = 1;
 671        while i < selections.len() {
 672            if selections[i].start <= selections[i - 1].end {
 673                let removed = selections.remove(i);
 674                if removed.start < selections[i - 1].start {
 675                    selections[i - 1].start = removed.start;
 676                }
 677                if selections[i - 1].end < removed.end {
 678                    selections[i - 1].end = removed.end;
 679                }
 680            } else {
 681                i += 1;
 682            }
 683        }
 684
 685        self.collection.disjoint = Arc::from_iter(
 686            selections
 687                .into_iter()
 688                .map(|selection| selection_to_anchor_selection(selection, self.snapshot)),
 689        );
 690        self.collection.pending = None;
 691        self.selections_changed = true;
 692    }
 693
 694    pub fn select_anchors(&mut self, selections: Vec<Selection<Anchor>>) {
 695        let map = self.display_snapshot();
 696        let resolved_selections =
 697            resolve_selections_wrapping_blocks::<MultiBufferOffset, _>(&selections, &map)
 698                .collect::<Vec<_>>();
 699        self.select(resolved_selections);
 700    }
 701
 702    pub fn select_ranges<I, T>(&mut self, ranges: I)
 703    where
 704        I: IntoIterator<Item = Range<T>>,
 705        T: ToOffset,
 706    {
 707        let ranges = ranges
 708            .into_iter()
 709            .map(|range| range.start.to_offset(self.snapshot)..range.end.to_offset(self.snapshot));
 710        self.select_offset_ranges(ranges);
 711    }
 712
 713    fn select_offset_ranges<I>(&mut self, ranges: I)
 714    where
 715        I: IntoIterator<Item = Range<MultiBufferOffset>>,
 716    {
 717        let selections = ranges
 718            .into_iter()
 719            .map(|range| {
 720                let mut start = range.start;
 721                let mut end = range.end;
 722                let reversed = if start > end {
 723                    mem::swap(&mut start, &mut end);
 724                    true
 725                } else {
 726                    false
 727                };
 728                Selection {
 729                    id: post_inc(&mut self.collection.next_selection_id),
 730                    start,
 731                    end,
 732                    reversed,
 733                    goal: SelectionGoal::None,
 734                }
 735            })
 736            .collect::<Vec<_>>();
 737
 738        self.select(selections)
 739    }
 740
 741    pub fn select_anchor_ranges<I>(&mut self, ranges: I)
 742    where
 743        I: IntoIterator<Item = Range<Anchor>>,
 744    {
 745        let selections = ranges
 746            .into_iter()
 747            .map(|range| {
 748                let mut start = range.start;
 749                let mut end = range.end;
 750                let reversed = if start.cmp(&end, self.snapshot).is_gt() {
 751                    mem::swap(&mut start, &mut end);
 752                    true
 753                } else {
 754                    false
 755                };
 756                Selection {
 757                    id: post_inc(&mut self.collection.next_selection_id),
 758                    start,
 759                    end,
 760                    reversed,
 761                    goal: SelectionGoal::None,
 762                }
 763            })
 764            .collect::<Vec<_>>();
 765        self.select_anchors(selections)
 766    }
 767
 768    pub fn new_selection_id(&mut self) -> usize {
 769        post_inc(&mut self.next_selection_id)
 770    }
 771
 772    pub fn select_display_ranges<T>(&mut self, ranges: T)
 773    where
 774        T: IntoIterator<Item = Range<DisplayPoint>>,
 775    {
 776        let selections = ranges
 777            .into_iter()
 778            .map(|range| {
 779                let mut start = range.start;
 780                let mut end = range.end;
 781                let reversed = if start > end {
 782                    mem::swap(&mut start, &mut end);
 783                    true
 784                } else {
 785                    false
 786                };
 787                Selection {
 788                    id: post_inc(&mut self.collection.next_selection_id),
 789                    start: start.to_point(self.snapshot),
 790                    end: end.to_point(self.snapshot),
 791                    reversed,
 792                    goal: SelectionGoal::None,
 793                }
 794            })
 795            .collect();
 796        self.select(selections);
 797    }
 798
 799    pub fn reverse_selections(&mut self) {
 800        let mut new_selections: Vec<Selection<Point>> = Vec::new();
 801        let disjoint = self.disjoint.clone();
 802        for selection in disjoint
 803            .iter()
 804            .sorted_by(|first, second| Ord::cmp(&second.id, &first.id))
 805            .collect::<Vec<&Selection<Anchor>>>()
 806        {
 807            new_selections.push(Selection {
 808                id: self.new_selection_id(),
 809                start: selection
 810                    .start
 811                    .to_display_point(self.snapshot)
 812                    .to_point(self.snapshot),
 813                end: selection
 814                    .end
 815                    .to_display_point(self.snapshot)
 816                    .to_point(self.snapshot),
 817                reversed: selection.reversed,
 818                goal: selection.goal,
 819            });
 820        }
 821        self.select(new_selections);
 822    }
 823
 824    pub fn move_with(
 825        &mut self,
 826        mut move_selection: impl FnMut(&DisplaySnapshot, &mut Selection<DisplayPoint>),
 827    ) {
 828        let mut changed = false;
 829        let display_map = self.display_snapshot();
 830        let selections = self.collection.all_display(&display_map);
 831        let selections = selections
 832            .into_iter()
 833            .map(|selection| {
 834                let mut moved_selection = selection.clone();
 835                move_selection(&display_map, &mut moved_selection);
 836                if selection != moved_selection {
 837                    changed = true;
 838                }
 839                moved_selection.map(|display_point| display_point.to_point(&display_map))
 840            })
 841            .collect();
 842
 843        if changed {
 844            self.select(selections)
 845        }
 846    }
 847
 848    pub fn move_offsets_with(
 849        &mut self,
 850        mut move_selection: impl FnMut(&MultiBufferSnapshot, &mut Selection<MultiBufferOffset>),
 851    ) {
 852        let mut changed = false;
 853        let display_map = self.display_snapshot();
 854        let selections = self
 855            .collection
 856            .all::<MultiBufferOffset>(&display_map)
 857            .into_iter()
 858            .map(|selection| {
 859                let mut moved_selection = selection.clone();
 860                move_selection(self.snapshot, &mut moved_selection);
 861                if selection != moved_selection {
 862                    changed = true;
 863                }
 864                moved_selection
 865            })
 866            .collect();
 867
 868        if changed {
 869            self.select(selections)
 870        }
 871    }
 872
 873    pub fn move_heads_with(
 874        &mut self,
 875        mut update_head: impl FnMut(
 876            &DisplaySnapshot,
 877            DisplayPoint,
 878            SelectionGoal,
 879        ) -> (DisplayPoint, SelectionGoal),
 880    ) {
 881        self.move_with(|map, selection| {
 882            let (new_head, new_goal) = update_head(map, selection.head(), selection.goal);
 883            selection.set_head(new_head, new_goal);
 884        });
 885    }
 886
 887    pub fn move_cursors_with(
 888        &mut self,
 889        mut update_cursor_position: impl FnMut(
 890            &DisplaySnapshot,
 891            DisplayPoint,
 892            SelectionGoal,
 893        ) -> (DisplayPoint, SelectionGoal),
 894    ) {
 895        self.move_with(|map, selection| {
 896            let (cursor, new_goal) = update_cursor_position(map, selection.head(), selection.goal);
 897            selection.collapse_to(cursor, new_goal)
 898        });
 899    }
 900
 901    pub fn maybe_move_cursors_with(
 902        &mut self,
 903        mut update_cursor_position: impl FnMut(
 904            &DisplaySnapshot,
 905            DisplayPoint,
 906            SelectionGoal,
 907        ) -> Option<(DisplayPoint, SelectionGoal)>,
 908    ) {
 909        self.move_cursors_with(|map, point, goal| {
 910            update_cursor_position(map, point, goal).unwrap_or((point, goal))
 911        })
 912    }
 913
 914    pub fn replace_cursors_with(
 915        &mut self,
 916        find_replacement_cursors: impl FnOnce(&DisplaySnapshot) -> Vec<DisplayPoint>,
 917    ) {
 918        let new_selections = find_replacement_cursors(self.snapshot)
 919            .into_iter()
 920            .map(|cursor| {
 921                let cursor_point = cursor.to_point(self.snapshot);
 922                Selection {
 923                    id: post_inc(&mut self.collection.next_selection_id),
 924                    start: cursor_point,
 925                    end: cursor_point,
 926                    reversed: false,
 927                    goal: SelectionGoal::None,
 928                }
 929            })
 930            .collect();
 931        self.select(new_selections);
 932    }
 933
 934    /// Compute new ranges for any selections that were located in excerpts that have
 935    /// since been removed.
 936    ///
 937    /// Returns a `HashMap` indicating which selections whose former head position
 938    /// was no longer present. The keys of the map are selection ids. The values are
 939    /// the id of the new excerpt where the head of the selection has been moved.
 940    pub fn refresh(&mut self) -> HashMap<usize, ExcerptId> {
 941        let mut pending = self.collection.pending.take();
 942        let mut selections_with_lost_position = HashMap::default();
 943
 944        let anchors_with_status = {
 945            let disjoint_anchors = self
 946                .disjoint
 947                .iter()
 948                .flat_map(|selection| [&selection.start, &selection.end]);
 949            self.snapshot.refresh_anchors(disjoint_anchors)
 950        };
 951        let adjusted_disjoint: Vec<_> = anchors_with_status
 952            .chunks(2)
 953            .map(|selection_anchors| {
 954                let (anchor_ix, start, kept_start) = selection_anchors[0];
 955                let (_, end, kept_end) = selection_anchors[1];
 956                let selection = &self.disjoint[anchor_ix / 2];
 957                let kept_head = if selection.reversed {
 958                    kept_start
 959                } else {
 960                    kept_end
 961                };
 962                if !kept_head {
 963                    selections_with_lost_position.insert(selection.id, selection.head().excerpt_id);
 964                }
 965
 966                Selection {
 967                    id: selection.id,
 968                    start,
 969                    end,
 970                    reversed: selection.reversed,
 971                    goal: selection.goal,
 972                }
 973            })
 974            .collect();
 975
 976        if !adjusted_disjoint.is_empty() {
 977            let map = self.display_snapshot();
 978            let resolved_selections =
 979                resolve_selections_wrapping_blocks(adjusted_disjoint.iter(), &map).collect();
 980            self.select::<MultiBufferOffset>(resolved_selections);
 981        }
 982
 983        if let Some(pending) = pending.as_mut() {
 984            let anchors = self
 985                .snapshot
 986                .refresh_anchors([&pending.selection.start, &pending.selection.end]);
 987            let (_, start, kept_start) = anchors[0];
 988            let (_, end, kept_end) = anchors[1];
 989            let kept_head = if pending.selection.reversed {
 990                kept_start
 991            } else {
 992                kept_end
 993            };
 994            if !kept_head {
 995                selections_with_lost_position
 996                    .insert(pending.selection.id, pending.selection.head().excerpt_id);
 997            }
 998
 999            pending.selection.start = start;
1000            pending.selection.end = end;
1001        }
1002        self.collection.pending = pending;
1003        self.selections_changed = true;
1004
1005        selections_with_lost_position
1006    }
1007}
1008
1009impl Deref for MutableSelectionsCollection<'_, '_> {
1010    type Target = SelectionsCollection;
1011    fn deref(&self) -> &Self::Target {
1012        self.collection
1013    }
1014}
1015
1016impl DerefMut for MutableSelectionsCollection<'_, '_> {
1017    fn deref_mut(&mut self) -> &mut Self::Target {
1018        self.collection
1019    }
1020}
1021
1022fn selection_to_anchor_selection(
1023    selection: Selection<MultiBufferOffset>,
1024    buffer: &MultiBufferSnapshot,
1025) -> Selection<Anchor> {
1026    let end_bias = if selection.start == selection.end {
1027        Bias::Right
1028    } else {
1029        Bias::Left
1030    };
1031    Selection {
1032        id: selection.id,
1033        start: buffer.anchor_after(selection.start),
1034        end: buffer.anchor_at(selection.end, end_bias),
1035        reversed: selection.reversed,
1036        goal: selection.goal,
1037    }
1038}
1039
1040fn resolve_selections_point<'a>(
1041    selections: impl 'a + IntoIterator<Item = &'a Selection<Anchor>>,
1042    map: &'a DisplaySnapshot,
1043) -> impl 'a + Iterator<Item = Selection<Point>> {
1044    let (to_summarize, selections) = selections.into_iter().tee();
1045    let mut summaries = map
1046        .buffer_snapshot()
1047        .summaries_for_anchors::<Point, _>(to_summarize.flat_map(|s| [&s.start, &s.end]))
1048        .into_iter();
1049    selections.map(move |s| {
1050        let start = summaries.next().unwrap();
1051        let end = summaries.next().unwrap();
1052        assert!(start <= end, "start: {:?}, end: {:?}", start, end);
1053        Selection {
1054            id: s.id,
1055            start,
1056            end,
1057            reversed: s.reversed,
1058            goal: s.goal,
1059        }
1060    })
1061}
1062
1063/// Panics if passed selections are not in order
1064/// Resolves the anchors to display positions
1065fn resolve_selections_display<'a>(
1066    selections: impl 'a + IntoIterator<Item = &'a Selection<Anchor>>,
1067    map: &'a DisplaySnapshot,
1068) -> impl 'a + Iterator<Item = Selection<DisplayPoint>> {
1069    let selections = resolve_selections_point(selections, map).map(move |s| {
1070        let display_start = map.point_to_display_point(s.start, Bias::Left);
1071        let display_end = map.point_to_display_point(
1072            s.end,
1073            if s.start == s.end {
1074                Bias::Right
1075            } else {
1076                Bias::Left
1077            },
1078        );
1079        assert!(
1080            display_start <= display_end,
1081            "display_start: {:?}, display_end: {:?}",
1082            display_start,
1083            display_end
1084        );
1085        Selection {
1086            id: s.id,
1087            start: display_start,
1088            end: display_end,
1089            reversed: s.reversed,
1090            goal: s.goal,
1091        }
1092    });
1093    coalesce_selections(selections)
1094}
1095
1096/// Resolves the passed in anchors to [`MultiBufferDimension`]s `D`
1097/// wrapping around blocks inbetween.
1098///
1099/// # Panics
1100///
1101/// Panics if passed selections are not in order
1102pub(crate) fn resolve_selections_wrapping_blocks<'a, D, I>(
1103    selections: I,
1104    map: &'a DisplaySnapshot,
1105) -> impl 'a + Iterator<Item = Selection<D>>
1106where
1107    D: MultiBufferDimension + Sub + AddAssign<<D as Sub>::Output> + Ord,
1108    I: 'a + IntoIterator<Item = &'a Selection<Anchor>>,
1109{
1110    // Transforms `Anchor -> DisplayPoint -> Point -> DisplayPoint -> D`
1111    // todo(lw): We should be able to short circuit the `Anchor -> DisplayPoint -> Point` to `Anchor -> Point`
1112    let (to_convert, selections) = resolve_selections_display(selections, map).tee();
1113    let mut converted_endpoints =
1114        map.buffer_snapshot()
1115            .dimensions_from_points::<D>(to_convert.flat_map(|s| {
1116                let start = map.display_point_to_point(s.start, Bias::Left);
1117                let end = map.display_point_to_point(s.end, Bias::Right);
1118                assert!(start <= end, "start: {:?}, end: {:?}", start, end);
1119                [start, end]
1120            }));
1121    selections.map(move |s| {
1122        let start = converted_endpoints.next().unwrap();
1123        let end = converted_endpoints.next().unwrap();
1124        assert!(start <= end, "start: {:?}, end: {:?}", start, end);
1125        Selection {
1126            id: s.id,
1127            start,
1128            end,
1129            reversed: s.reversed,
1130            goal: s.goal,
1131        }
1132    })
1133}
1134
1135fn coalesce_selections<D: Ord + fmt::Debug + Copy>(
1136    selections: impl Iterator<Item = Selection<D>>,
1137) -> impl Iterator<Item = Selection<D>> {
1138    let mut selections = selections.peekable();
1139    iter::from_fn(move || {
1140        let mut selection = selections.next()?;
1141        while let Some(next_selection) = selections.peek() {
1142            if selection.end >= next_selection.start {
1143                if selection.reversed == next_selection.reversed {
1144                    selection.end = cmp::max(selection.end, next_selection.end);
1145                    selections.next();
1146                } else {
1147                    selection.end = cmp::max(selection.start, next_selection.start);
1148                    break;
1149                }
1150            } else {
1151                break;
1152            }
1153        }
1154        assert!(
1155            selection.start <= selection.end,
1156            "selection.start: {:?}, selection.end: {:?}, selection.reversed: {:?}",
1157            selection.start,
1158            selection.end,
1159            selection.reversed
1160        );
1161        Some(selection)
1162    })
1163}