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 should_merge(
 140                        pending.start,
 141                        pending.end,
 142                        next_selection.start,
 143                        next_selection.end,
 144                        false,
 145                    ) {
 146                        let next_selection = disjoint.next().unwrap();
 147                        if next_selection.start < pending.start {
 148                            pending.start = next_selection.start;
 149                        }
 150                        if next_selection.end > pending.end {
 151                            pending.end = next_selection.end;
 152                        }
 153                    } else if next_selection.end < pending.start {
 154                        return disjoint.next();
 155                    } else {
 156                        break;
 157                    }
 158                }
 159
 160                pending_opt.take()
 161            } else {
 162                disjoint.next()
 163            }
 164        })
 165        .collect()
 166    }
 167
 168    /// Returns all of the selections, adjusted to take into account the selection line_mode
 169    pub fn all_adjusted(&self, snapshot: &DisplaySnapshot) -> Vec<Selection<Point>> {
 170        let mut selections = self.all::<Point>(&snapshot);
 171        if self.line_mode {
 172            for selection in &mut selections {
 173                let new_range = snapshot.expand_to_line(selection.range());
 174                selection.start = new_range.start;
 175                selection.end = new_range.end;
 176            }
 177        }
 178        selections
 179    }
 180
 181    /// Returns the newest selection, adjusted to take into account the selection line_mode
 182    pub fn newest_adjusted(&self, snapshot: &DisplaySnapshot) -> Selection<Point> {
 183        let mut selection = self.newest::<Point>(&snapshot);
 184        if self.line_mode {
 185            let new_range = snapshot.expand_to_line(selection.range());
 186            selection.start = new_range.start;
 187            selection.end = new_range.end;
 188        }
 189        selection
 190    }
 191
 192    pub fn all_adjusted_display(
 193        &self,
 194        display_map: &DisplaySnapshot,
 195    ) -> Vec<Selection<DisplayPoint>> {
 196        if self.line_mode {
 197            let selections = self.all::<Point>(&display_map);
 198            let result = selections
 199                .into_iter()
 200                .map(|mut selection| {
 201                    let new_range = display_map.expand_to_line(selection.range());
 202                    selection.start = new_range.start;
 203                    selection.end = new_range.end;
 204                    selection.map(|point| point.to_display_point(&display_map))
 205                })
 206                .collect();
 207            result
 208        } else {
 209            self.all_display(display_map)
 210        }
 211    }
 212
 213    pub fn disjoint_in_range<D>(
 214        &self,
 215        range: Range<Anchor>,
 216        snapshot: &DisplaySnapshot,
 217    ) -> Vec<Selection<D>>
 218    where
 219        D: MultiBufferDimension + Sub + AddAssign<<D as Sub>::Output> + Ord + std::fmt::Debug,
 220    {
 221        let start_ix = match self
 222            .disjoint
 223            .binary_search_by(|probe| probe.end.cmp(&range.start, snapshot.buffer_snapshot()))
 224        {
 225            Ok(ix) | Err(ix) => ix,
 226        };
 227        let end_ix = match self
 228            .disjoint
 229            .binary_search_by(|probe| probe.start.cmp(&range.end, snapshot.buffer_snapshot()))
 230        {
 231            Ok(ix) => ix + 1,
 232            Err(ix) => ix,
 233        };
 234        resolve_selections_wrapping_blocks(&self.disjoint[start_ix..end_ix], snapshot).collect()
 235    }
 236
 237    pub fn all_display(&self, snapshot: &DisplaySnapshot) -> Vec<Selection<DisplayPoint>> {
 238        let disjoint_anchors = &self.disjoint;
 239        let mut disjoint =
 240            resolve_selections_display(disjoint_anchors.iter(), &snapshot).peekable();
 241        let mut pending_opt = resolve_selections_display(self.pending_anchor(), &snapshot).next();
 242        iter::from_fn(move || {
 243            if let Some(pending) = pending_opt.as_mut() {
 244                while let Some(next_selection) = disjoint.peek() {
 245                    if should_merge(
 246                        pending.start,
 247                        pending.end,
 248                        next_selection.start,
 249                        next_selection.end,
 250                        false,
 251                    ) {
 252                        let next_selection = disjoint.next().unwrap();
 253                        if next_selection.start < pending.start {
 254                            pending.start = next_selection.start;
 255                        }
 256                        if next_selection.end > pending.end {
 257                            pending.end = next_selection.end;
 258                        }
 259                    } else if next_selection.end < pending.start {
 260                        return disjoint.next();
 261                    } else {
 262                        break;
 263                    }
 264                }
 265
 266                pending_opt.take()
 267            } else {
 268                disjoint.next()
 269            }
 270        })
 271        .collect()
 272    }
 273
 274    pub fn newest_anchor(&self) -> &Selection<Anchor> {
 275        self.pending
 276            .as_ref()
 277            .map(|s| &s.selection)
 278            .or_else(|| self.disjoint.iter().max_by_key(|s| s.id))
 279            .unwrap()
 280    }
 281
 282    pub fn newest<D>(&self, snapshot: &DisplaySnapshot) -> Selection<D>
 283    where
 284        D: MultiBufferDimension + Sub + AddAssign<<D as Sub>::Output> + Ord,
 285    {
 286        resolve_selections_wrapping_blocks([self.newest_anchor()], &snapshot)
 287            .next()
 288            .unwrap()
 289    }
 290
 291    pub fn newest_display(&self, snapshot: &DisplaySnapshot) -> Selection<DisplayPoint> {
 292        resolve_selections_display([self.newest_anchor()], &snapshot)
 293            .next()
 294            .unwrap()
 295    }
 296
 297    pub fn oldest_anchor(&self) -> &Selection<Anchor> {
 298        self.disjoint
 299            .iter()
 300            .min_by_key(|s| s.id)
 301            .or_else(|| self.pending.as_ref().map(|p| &p.selection))
 302            .unwrap()
 303    }
 304
 305    pub fn oldest<D>(&self, snapshot: &DisplaySnapshot) -> Selection<D>
 306    where
 307        D: MultiBufferDimension + Sub + AddAssign<<D as Sub>::Output> + Ord,
 308    {
 309        resolve_selections_wrapping_blocks([self.oldest_anchor()], &snapshot)
 310            .next()
 311            .unwrap()
 312    }
 313
 314    pub fn first_anchor(&self) -> Selection<Anchor> {
 315        self.pending
 316            .as_ref()
 317            .map(|pending| pending.selection.clone())
 318            .unwrap_or_else(|| self.disjoint.first().cloned().unwrap())
 319    }
 320
 321    pub fn first<D>(&self, snapshot: &DisplaySnapshot) -> Selection<D>
 322    where
 323        D: MultiBufferDimension + Sub + AddAssign<<D as Sub>::Output> + Ord,
 324    {
 325        self.all(snapshot).first().unwrap().clone()
 326    }
 327
 328    pub fn last<D>(&self, snapshot: &DisplaySnapshot) -> Selection<D>
 329    where
 330        D: MultiBufferDimension + Sub + AddAssign<<D as Sub>::Output> + Ord,
 331    {
 332        self.all(snapshot).last().unwrap().clone()
 333    }
 334
 335    /// Returns a list of (potentially backwards!) ranges representing the selections.
 336    /// Useful for test assertions, but prefer `.all()` instead.
 337    #[cfg(any(test, feature = "test-support"))]
 338    pub fn ranges<D>(&self, snapshot: &DisplaySnapshot) -> Vec<Range<D>>
 339    where
 340        D: MultiBufferDimension + Sub + AddAssign<<D as Sub>::Output> + Ord,
 341    {
 342        self.all::<D>(snapshot)
 343            .iter()
 344            .map(|s| {
 345                if s.reversed {
 346                    s.end..s.start
 347                } else {
 348                    s.start..s.end
 349                }
 350            })
 351            .collect()
 352    }
 353
 354    #[cfg(any(test, feature = "test-support"))]
 355    pub fn display_ranges(&self, display_snapshot: &DisplaySnapshot) -> Vec<Range<DisplayPoint>> {
 356        self.disjoint_anchors_arc()
 357            .iter()
 358            .chain(self.pending_anchor())
 359            .map(|s| {
 360                if s.reversed {
 361                    s.end.to_display_point(display_snapshot)
 362                        ..s.start.to_display_point(display_snapshot)
 363                } else {
 364                    s.start.to_display_point(display_snapshot)
 365                        ..s.end.to_display_point(display_snapshot)
 366                }
 367            })
 368            .collect()
 369    }
 370
 371    /// Attempts to build a selection in the provided `DisplayRow` within the
 372    /// same range as the provided range of `Pixels`.
 373    /// Returns `None` if the range is not empty but it starts past the line's
 374    /// length, meaning that the line isn't long enough to be contained within
 375    /// part of the provided range.
 376    pub fn build_columnar_selection(
 377        &mut self,
 378        display_map: &DisplaySnapshot,
 379        row: DisplayRow,
 380        positions: &Range<Pixels>,
 381        reversed: bool,
 382        text_layout_details: &TextLayoutDetails,
 383    ) -> Option<Selection<Point>> {
 384        let is_empty = positions.start == positions.end;
 385        let line_len = display_map.line_len(row);
 386        let line = display_map.layout_row(row, text_layout_details);
 387        let start_col = line.closest_index_for_x(positions.start) as u32;
 388
 389        let (start, end) = if is_empty {
 390            let point = DisplayPoint::new(row, std::cmp::min(start_col, line_len));
 391            (point, point)
 392        } else {
 393            if start_col >= line_len {
 394                return None;
 395            }
 396            let start = DisplayPoint::new(row, start_col);
 397            let end_col = line.closest_index_for_x(positions.end) as u32;
 398            let end = DisplayPoint::new(row, end_col);
 399            (start, end)
 400        };
 401
 402        Some(Selection {
 403            id: post_inc(&mut self.next_selection_id),
 404            start: start.to_point(display_map),
 405            end: end.to_point(display_map),
 406            reversed,
 407            goal: SelectionGoal::HorizontalRange {
 408                start: positions.start.into(),
 409                end: positions.end.into(),
 410            },
 411        })
 412    }
 413
 414    /// Attempts to build a selection in the provided buffer row using the
 415    /// same buffer column range as specified.
 416    /// Returns `None` if the range is not empty but it starts past the line's
 417    /// length, meaning that the line isn't long enough to be contained within
 418    /// part of the provided range.
 419    pub fn build_columnar_selection_from_buffer_columns(
 420        &mut self,
 421        display_map: &DisplaySnapshot,
 422        buffer_row: u32,
 423        positions: &Range<u32>,
 424        reversed: bool,
 425        text_layout_details: &TextLayoutDetails,
 426    ) -> Option<Selection<Point>> {
 427        let is_empty = positions.start == positions.end;
 428        let line_len = display_map
 429            .buffer_snapshot()
 430            .line_len(multi_buffer::MultiBufferRow(buffer_row));
 431
 432        let (start, end) = if is_empty {
 433            let column = std::cmp::min(positions.start, line_len);
 434            let point = Point::new(buffer_row, column);
 435            (point, point)
 436        } else {
 437            if positions.start >= line_len {
 438                return None;
 439            }
 440
 441            let start = Point::new(buffer_row, positions.start);
 442            let end_column = std::cmp::min(positions.end, line_len);
 443            let end = Point::new(buffer_row, end_column);
 444            (start, end)
 445        };
 446
 447        let start_display_point = start.to_display_point(display_map);
 448        let end_display_point = end.to_display_point(display_map);
 449        let start_x = display_map.x_for_display_point(start_display_point, text_layout_details);
 450        let end_x = display_map.x_for_display_point(end_display_point, text_layout_details);
 451
 452        Some(Selection {
 453            id: post_inc(&mut self.next_selection_id),
 454            start,
 455            end,
 456            reversed,
 457            goal: SelectionGoal::HorizontalRange {
 458                start: start_x.min(end_x).into(),
 459                end: start_x.max(end_x).into(),
 460            },
 461        })
 462    }
 463
 464    /// Finds the next columnar selection by walking display rows one at a time
 465    /// so that soft-wrapped lines are considered and not skipped.
 466    pub fn find_next_columnar_selection_by_display_row(
 467        &mut self,
 468        display_map: &DisplaySnapshot,
 469        start_row: DisplayRow,
 470        end_row: DisplayRow,
 471        above: bool,
 472        positions: &Range<Pixels>,
 473        reversed: bool,
 474        text_layout_details: &TextLayoutDetails,
 475    ) -> Option<Selection<Point>> {
 476        let mut row = start_row;
 477        while row != end_row {
 478            if above {
 479                row.0 -= 1;
 480            } else {
 481                row.0 += 1;
 482            }
 483
 484            if let Some(selection) = self.build_columnar_selection(
 485                display_map,
 486                row,
 487                positions,
 488                reversed,
 489                text_layout_details,
 490            ) {
 491                return Some(selection);
 492            }
 493        }
 494        None
 495    }
 496
 497    /// Finds the next columnar selection by skipping to the next buffer row,
 498    /// ignoring soft-wrapped lines.
 499    pub fn find_next_columnar_selection_by_buffer_row(
 500        &mut self,
 501        display_map: &DisplaySnapshot,
 502        start_row: DisplayRow,
 503        end_row: DisplayRow,
 504        above: bool,
 505        goal_columns: &Range<u32>,
 506        reversed: bool,
 507        text_layout_details: &TextLayoutDetails,
 508    ) -> Option<Selection<Point>> {
 509        let mut row = start_row;
 510        let direction = if above { -1 } else { 1 };
 511        while row != end_row {
 512            let new_row =
 513                display_map.start_of_relative_buffer_row(DisplayPoint::new(row, 0), direction);
 514            row = new_row.row();
 515            let buffer_row = new_row.to_point(display_map).row;
 516
 517            if let Some(selection) = self.build_columnar_selection_from_buffer_columns(
 518                display_map,
 519                buffer_row,
 520                goal_columns,
 521                reversed,
 522                text_layout_details,
 523            ) {
 524                return Some(selection);
 525            }
 526        }
 527        None
 528    }
 529
 530    pub fn change_with<R>(
 531        &mut self,
 532        snapshot: &DisplaySnapshot,
 533        change: impl FnOnce(&mut MutableSelectionsCollection<'_, '_>) -> R,
 534    ) -> (bool, R) {
 535        let mut mutable_collection = MutableSelectionsCollection {
 536            snapshot,
 537            collection: self,
 538            selections_changed: false,
 539        };
 540
 541        let result = change(&mut mutable_collection);
 542        assert!(
 543            !mutable_collection.disjoint.is_empty() || mutable_collection.pending.is_some(),
 544            "There must be at least one selection"
 545        );
 546        if cfg!(debug_assertions) {
 547            mutable_collection.disjoint.iter().for_each(|selection| {
 548                assert!(
 549                    snapshot.can_resolve(&selection.start),
 550                    "disjoint selection start is not resolvable for the given snapshot:\n{selection:?}, {excerpt:?}",
 551                    excerpt = snapshot.buffer_for_excerpt(selection.start.excerpt_id).map(|snapshot| snapshot.remote_id()),
 552                );
 553                assert!(
 554                    snapshot.can_resolve(&selection.end),
 555                    "disjoint selection end is not resolvable for the given snapshot: {selection:?}, {excerpt:?}",
 556                    excerpt = snapshot.buffer_for_excerpt(selection.end.excerpt_id).map(|snapshot| snapshot.remote_id()),
 557                );
 558            });
 559            if let Some(pending) = &mutable_collection.pending {
 560                let selection = &pending.selection;
 561                assert!(
 562                    snapshot.can_resolve(&selection.start),
 563                    "pending selection start is not resolvable for the given snapshot: {pending:?}, {excerpt:?}",
 564                    excerpt = snapshot
 565                        .buffer_for_excerpt(selection.start.excerpt_id)
 566                        .map(|snapshot| snapshot.remote_id()),
 567                );
 568                assert!(
 569                    snapshot.can_resolve(&selection.end),
 570                    "pending selection end is not resolvable for the given snapshot: {pending:?}, {excerpt:?}",
 571                    excerpt = snapshot
 572                        .buffer_for_excerpt(selection.end.excerpt_id)
 573                        .map(|snapshot| snapshot.remote_id()),
 574                );
 575            }
 576        }
 577        (mutable_collection.selections_changed, result)
 578    }
 579
 580    pub fn next_selection_id(&self) -> usize {
 581        self.next_selection_id
 582    }
 583
 584    pub fn line_mode(&self) -> bool {
 585        self.line_mode
 586    }
 587
 588    pub fn set_line_mode(&mut self, line_mode: bool) {
 589        self.line_mode = line_mode;
 590    }
 591
 592    pub fn select_mode(&self) -> &SelectMode {
 593        &self.select_mode
 594    }
 595
 596    pub fn set_select_mode(&mut self, select_mode: SelectMode) {
 597        self.select_mode = select_mode;
 598    }
 599
 600    pub fn is_extending(&self) -> bool {
 601        self.is_extending
 602    }
 603
 604    pub fn set_is_extending(&mut self, is_extending: bool) {
 605        self.is_extending = is_extending;
 606    }
 607}
 608
 609pub struct MutableSelectionsCollection<'snap, 'a> {
 610    collection: &'a mut SelectionsCollection,
 611    snapshot: &'snap DisplaySnapshot,
 612    selections_changed: bool,
 613}
 614
 615impl<'snap, 'a> fmt::Debug for MutableSelectionsCollection<'snap, 'a> {
 616    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 617        f.debug_struct("MutableSelectionsCollection")
 618            .field("collection", &self.collection)
 619            .field("selections_changed", &self.selections_changed)
 620            .finish()
 621    }
 622}
 623
 624impl<'snap, 'a> MutableSelectionsCollection<'snap, 'a> {
 625    pub fn display_snapshot(&self) -> DisplaySnapshot {
 626        self.snapshot.clone()
 627    }
 628
 629    pub fn clear_disjoint(&mut self) {
 630        self.collection.disjoint = Arc::default();
 631    }
 632
 633    pub fn delete(&mut self, selection_id: usize) {
 634        let mut changed = false;
 635        self.collection.disjoint = self
 636            .disjoint
 637            .iter()
 638            .filter(|selection| {
 639                let found = selection.id == selection_id;
 640                changed |= found;
 641                !found
 642            })
 643            .cloned()
 644            .collect();
 645
 646        self.selections_changed |= changed;
 647    }
 648
 649    pub fn remove_selections_from_buffer(&mut self, buffer_id: language::BufferId) {
 650        let mut changed = false;
 651
 652        let filtered_selections: Arc<[Selection<Anchor>]> = {
 653            self.disjoint
 654                .iter()
 655                .filter(|selection| {
 656                    if let Some(selection_buffer_id) =
 657                        self.snapshot.buffer_id_for_anchor(selection.start)
 658                    {
 659                        let should_remove = selection_buffer_id == buffer_id;
 660                        changed |= should_remove;
 661                        !should_remove
 662                    } else {
 663                        true
 664                    }
 665                })
 666                .cloned()
 667                .collect()
 668        };
 669
 670        if filtered_selections.is_empty() {
 671            let buffer_snapshot = self.snapshot.buffer_snapshot();
 672            let anchor = buffer_snapshot
 673                .excerpts()
 674                .find(|(_, buffer, _)| buffer.remote_id() == buffer_id)
 675                .and_then(|(excerpt_id, _, range)| {
 676                    buffer_snapshot.anchor_in_excerpt(excerpt_id, range.context.start)
 677                })
 678                .unwrap_or_else(|| self.snapshot.anchor_before(MultiBufferOffset(0)));
 679            self.collection.disjoint = Arc::from([Selection {
 680                id: post_inc(&mut self.collection.next_selection_id),
 681                start: anchor,
 682                end: anchor,
 683                reversed: false,
 684                goal: SelectionGoal::None,
 685            }]);
 686        } else {
 687            self.collection.disjoint = filtered_selections;
 688        }
 689
 690        self.selections_changed |= changed;
 691    }
 692
 693    pub fn clear_pending(&mut self) {
 694        if self.collection.pending.is_some() {
 695            self.collection.pending = None;
 696            self.selections_changed = true;
 697        }
 698    }
 699
 700    pub(crate) fn set_pending_anchor_range(&mut self, range: Range<Anchor>, mode: SelectMode) {
 701        self.collection.pending = Some(PendingSelection {
 702            selection: {
 703                let mut start = range.start;
 704                let mut end = range.end;
 705                let reversed = if start.cmp(&end, self.snapshot).is_gt() {
 706                    mem::swap(&mut start, &mut end);
 707                    true
 708                } else {
 709                    false
 710                };
 711                Selection {
 712                    id: post_inc(&mut self.collection.next_selection_id),
 713                    start,
 714                    end,
 715                    reversed,
 716                    goal: SelectionGoal::None,
 717                }
 718            },
 719            mode,
 720        });
 721        self.selections_changed = true;
 722    }
 723
 724    pub(crate) fn set_pending(&mut self, selection: Selection<Anchor>, mode: SelectMode) {
 725        self.collection.pending = Some(PendingSelection { selection, mode });
 726        self.selections_changed = true;
 727    }
 728
 729    pub fn try_cancel(&mut self) -> bool {
 730        if let Some(pending) = self.collection.pending.take() {
 731            if self.disjoint.is_empty() {
 732                self.collection.disjoint = Arc::from([pending.selection]);
 733            }
 734            self.selections_changed = true;
 735            return true;
 736        }
 737
 738        let mut oldest = self.oldest_anchor().clone();
 739        if self.count() > 1 {
 740            self.collection.disjoint = Arc::from([oldest]);
 741            self.selections_changed = true;
 742            return true;
 743        }
 744
 745        if !oldest.start.cmp(&oldest.end, self.snapshot).is_eq() {
 746            let head = oldest.head();
 747            oldest.start = head;
 748            oldest.end = head;
 749            self.collection.disjoint = Arc::from([oldest]);
 750            self.selections_changed = true;
 751            return true;
 752        }
 753
 754        false
 755    }
 756
 757    pub fn insert_range<T>(&mut self, range: Range<T>)
 758    where
 759        T: ToOffset,
 760    {
 761        let display_map = self.display_snapshot();
 762        let mut selections = self.collection.all(&display_map);
 763        let mut start = range.start.to_offset(self.snapshot);
 764        let mut end = range.end.to_offset(self.snapshot);
 765        let reversed = if start > end {
 766            mem::swap(&mut start, &mut end);
 767            true
 768        } else {
 769            false
 770        };
 771        selections.push(Selection {
 772            id: post_inc(&mut self.collection.next_selection_id),
 773            start,
 774            end,
 775            reversed,
 776            goal: SelectionGoal::None,
 777        });
 778        self.select(selections);
 779    }
 780
 781    pub fn select<T>(&mut self, selections: Vec<Selection<T>>)
 782    where
 783        T: ToOffset + std::marker::Copy + std::fmt::Debug,
 784    {
 785        let mut selections = selections
 786            .into_iter()
 787            .map(|selection| selection.map(|it| it.to_offset(self.snapshot)))
 788            .map(|mut selection| {
 789                if selection.start > selection.end {
 790                    mem::swap(&mut selection.start, &mut selection.end);
 791                    selection.reversed = true
 792                }
 793                selection
 794            })
 795            .collect::<Vec<_>>();
 796        selections.sort_unstable_by_key(|s| s.start);
 797
 798        let mut i = 1;
 799        while i < selections.len() {
 800            let prev = &selections[i - 1];
 801            let current = &selections[i];
 802
 803            if should_merge(prev.start, prev.end, current.start, current.end, true) {
 804                let removed = selections.remove(i);
 805                if removed.start < selections[i - 1].start {
 806                    selections[i - 1].start = removed.start;
 807                }
 808                if selections[i - 1].end < removed.end {
 809                    selections[i - 1].end = removed.end;
 810                }
 811            } else {
 812                i += 1;
 813            }
 814        }
 815
 816        self.collection.disjoint = Arc::from_iter(
 817            selections
 818                .into_iter()
 819                .map(|selection| selection_to_anchor_selection(selection, self.snapshot)),
 820        );
 821        self.collection.pending = None;
 822        self.selections_changed = true;
 823    }
 824
 825    pub fn select_anchors(&mut self, selections: Vec<Selection<Anchor>>) {
 826        let map = self.display_snapshot();
 827        let resolved_selections =
 828            resolve_selections_wrapping_blocks::<MultiBufferOffset, _>(&selections, &map)
 829                .collect::<Vec<_>>();
 830        self.select(resolved_selections);
 831    }
 832
 833    pub fn select_ranges<I, T>(&mut self, ranges: I)
 834    where
 835        I: IntoIterator<Item = Range<T>>,
 836        T: ToOffset,
 837    {
 838        let ranges = ranges
 839            .into_iter()
 840            .map(|range| range.start.to_offset(self.snapshot)..range.end.to_offset(self.snapshot));
 841        self.select_offset_ranges(ranges);
 842    }
 843
 844    fn select_offset_ranges<I>(&mut self, ranges: I)
 845    where
 846        I: IntoIterator<Item = Range<MultiBufferOffset>>,
 847    {
 848        let selections = ranges
 849            .into_iter()
 850            .map(|range| {
 851                let mut start = range.start;
 852                let mut end = range.end;
 853                let reversed = if start > end {
 854                    mem::swap(&mut start, &mut end);
 855                    true
 856                } else {
 857                    false
 858                };
 859                Selection {
 860                    id: post_inc(&mut self.collection.next_selection_id),
 861                    start,
 862                    end,
 863                    reversed,
 864                    goal: SelectionGoal::None,
 865                }
 866            })
 867            .collect::<Vec<_>>();
 868
 869        self.select(selections)
 870    }
 871
 872    pub fn select_anchor_ranges<I>(&mut self, ranges: I)
 873    where
 874        I: IntoIterator<Item = Range<Anchor>>,
 875    {
 876        let selections = ranges
 877            .into_iter()
 878            .map(|range| {
 879                let mut start = range.start;
 880                let mut end = range.end;
 881                let reversed = if start.cmp(&end, self.snapshot).is_gt() {
 882                    mem::swap(&mut start, &mut end);
 883                    true
 884                } else {
 885                    false
 886                };
 887                Selection {
 888                    id: post_inc(&mut self.collection.next_selection_id),
 889                    start,
 890                    end,
 891                    reversed,
 892                    goal: SelectionGoal::None,
 893                }
 894            })
 895            .collect::<Vec<_>>();
 896        self.select_anchors(selections)
 897    }
 898
 899    pub fn new_selection_id(&mut self) -> usize {
 900        post_inc(&mut self.next_selection_id)
 901    }
 902
 903    pub fn select_display_ranges<T>(&mut self, ranges: T)
 904    where
 905        T: IntoIterator<Item = Range<DisplayPoint>>,
 906    {
 907        let selections = ranges
 908            .into_iter()
 909            .map(|range| {
 910                let mut start = range.start;
 911                let mut end = range.end;
 912                let reversed = if start > end {
 913                    mem::swap(&mut start, &mut end);
 914                    true
 915                } else {
 916                    false
 917                };
 918                Selection {
 919                    id: post_inc(&mut self.collection.next_selection_id),
 920                    start: start.to_point(self.snapshot),
 921                    end: end.to_point(self.snapshot),
 922                    reversed,
 923                    goal: SelectionGoal::None,
 924                }
 925            })
 926            .collect();
 927        self.select(selections);
 928    }
 929
 930    pub fn reverse_selections(&mut self) {
 931        let mut new_selections: Vec<Selection<Point>> = Vec::new();
 932        let disjoint = self.disjoint.clone();
 933        for selection in disjoint
 934            .iter()
 935            .sorted_by(|first, second| Ord::cmp(&second.id, &first.id))
 936            .collect::<Vec<&Selection<Anchor>>>()
 937        {
 938            new_selections.push(Selection {
 939                id: self.new_selection_id(),
 940                start: selection
 941                    .start
 942                    .to_display_point(self.snapshot)
 943                    .to_point(self.snapshot),
 944                end: selection
 945                    .end
 946                    .to_display_point(self.snapshot)
 947                    .to_point(self.snapshot),
 948                reversed: selection.reversed,
 949                goal: selection.goal,
 950            });
 951        }
 952        self.select(new_selections);
 953    }
 954
 955    pub fn move_with(
 956        &mut self,
 957        mut move_selection: impl FnMut(&DisplaySnapshot, &mut Selection<DisplayPoint>),
 958    ) {
 959        let mut changed = false;
 960        let display_map = self.display_snapshot();
 961        let selections = self.collection.all_display(&display_map);
 962        let selections = selections
 963            .into_iter()
 964            .map(|selection| {
 965                let mut moved_selection = selection.clone();
 966                move_selection(&display_map, &mut moved_selection);
 967                if selection != moved_selection {
 968                    changed = true;
 969                }
 970                moved_selection.map(|display_point| display_point.to_point(&display_map))
 971            })
 972            .collect();
 973
 974        if changed {
 975            self.select(selections)
 976        }
 977    }
 978
 979    pub fn move_offsets_with(
 980        &mut self,
 981        mut move_selection: impl FnMut(&MultiBufferSnapshot, &mut Selection<MultiBufferOffset>),
 982    ) {
 983        let mut changed = false;
 984        let display_map = self.display_snapshot();
 985        let selections = self
 986            .collection
 987            .all::<MultiBufferOffset>(&display_map)
 988            .into_iter()
 989            .map(|selection| {
 990                let mut moved_selection = selection.clone();
 991                move_selection(self.snapshot, &mut moved_selection);
 992                if selection != moved_selection {
 993                    changed = true;
 994                }
 995                moved_selection
 996            })
 997            .collect();
 998
 999        if changed {
1000            self.select(selections)
1001        }
1002    }
1003
1004    pub fn move_heads_with(
1005        &mut self,
1006        mut update_head: impl FnMut(
1007            &DisplaySnapshot,
1008            DisplayPoint,
1009            SelectionGoal,
1010        ) -> (DisplayPoint, SelectionGoal),
1011    ) {
1012        self.move_with(|map, selection| {
1013            let (new_head, new_goal) = update_head(map, selection.head(), selection.goal);
1014            selection.set_head(new_head, new_goal);
1015        });
1016    }
1017
1018    pub fn move_cursors_with(
1019        &mut self,
1020        mut update_cursor_position: impl FnMut(
1021            &DisplaySnapshot,
1022            DisplayPoint,
1023            SelectionGoal,
1024        ) -> (DisplayPoint, SelectionGoal),
1025    ) {
1026        self.move_with(|map, selection| {
1027            let (cursor, new_goal) = update_cursor_position(map, selection.head(), selection.goal);
1028            selection.collapse_to(cursor, new_goal)
1029        });
1030    }
1031
1032    pub fn maybe_move_cursors_with(
1033        &mut self,
1034        mut update_cursor_position: impl FnMut(
1035            &DisplaySnapshot,
1036            DisplayPoint,
1037            SelectionGoal,
1038        ) -> Option<(DisplayPoint, SelectionGoal)>,
1039    ) {
1040        self.move_cursors_with(|map, point, goal| {
1041            update_cursor_position(map, point, goal).unwrap_or((point, goal))
1042        })
1043    }
1044
1045    pub fn replace_cursors_with(
1046        &mut self,
1047        find_replacement_cursors: impl FnOnce(&DisplaySnapshot) -> Vec<DisplayPoint>,
1048    ) {
1049        let new_selections = find_replacement_cursors(self.snapshot)
1050            .into_iter()
1051            .map(|cursor| {
1052                let cursor_point = cursor.to_point(self.snapshot);
1053                Selection {
1054                    id: post_inc(&mut self.collection.next_selection_id),
1055                    start: cursor_point,
1056                    end: cursor_point,
1057                    reversed: false,
1058                    goal: SelectionGoal::None,
1059                }
1060            })
1061            .collect();
1062        self.select(new_selections);
1063    }
1064
1065    /// Compute new ranges for any selections that were located in excerpts that have
1066    /// since been removed.
1067    ///
1068    /// Returns a `HashMap` indicating which selections whose former head position
1069    /// was no longer present. The keys of the map are selection ids. The values are
1070    /// the id of the new excerpt where the head of the selection has been moved.
1071    pub fn refresh(&mut self) -> HashMap<usize, ExcerptId> {
1072        let mut pending = self.collection.pending.take();
1073        let mut selections_with_lost_position = HashMap::default();
1074
1075        let anchors_with_status = {
1076            let disjoint_anchors = self
1077                .disjoint
1078                .iter()
1079                .flat_map(|selection| [&selection.start, &selection.end]);
1080            self.snapshot.refresh_anchors(disjoint_anchors)
1081        };
1082        let adjusted_disjoint: Vec<_> = anchors_with_status
1083            .chunks(2)
1084            .map(|selection_anchors| {
1085                let (anchor_ix, start, kept_start) = selection_anchors[0];
1086                let (_, end, kept_end) = selection_anchors[1];
1087                let selection = &self.disjoint[anchor_ix / 2];
1088                let kept_head = if selection.reversed {
1089                    kept_start
1090                } else {
1091                    kept_end
1092                };
1093                if !kept_head {
1094                    selections_with_lost_position.insert(selection.id, selection.head().excerpt_id);
1095                }
1096
1097                Selection {
1098                    id: selection.id,
1099                    start,
1100                    end,
1101                    reversed: selection.reversed,
1102                    goal: selection.goal,
1103                }
1104            })
1105            .collect();
1106
1107        if !adjusted_disjoint.is_empty() {
1108            let map = self.display_snapshot();
1109            let resolved_selections =
1110                resolve_selections_wrapping_blocks(adjusted_disjoint.iter(), &map).collect();
1111            self.select::<MultiBufferOffset>(resolved_selections);
1112        }
1113
1114        if let Some(pending) = pending.as_mut() {
1115            let anchors = self
1116                .snapshot
1117                .refresh_anchors([&pending.selection.start, &pending.selection.end]);
1118            let (_, start, kept_start) = anchors[0];
1119            let (_, end, kept_end) = anchors[1];
1120            let kept_head = if pending.selection.reversed {
1121                kept_start
1122            } else {
1123                kept_end
1124            };
1125            if !kept_head {
1126                selections_with_lost_position
1127                    .insert(pending.selection.id, pending.selection.head().excerpt_id);
1128            }
1129
1130            pending.selection.start = start;
1131            pending.selection.end = end;
1132        }
1133        self.collection.pending = pending;
1134        self.selections_changed = true;
1135
1136        selections_with_lost_position
1137    }
1138}
1139
1140impl Deref for MutableSelectionsCollection<'_, '_> {
1141    type Target = SelectionsCollection;
1142    fn deref(&self) -> &Self::Target {
1143        self.collection
1144    }
1145}
1146
1147impl DerefMut for MutableSelectionsCollection<'_, '_> {
1148    fn deref_mut(&mut self) -> &mut Self::Target {
1149        self.collection
1150    }
1151}
1152
1153fn selection_to_anchor_selection(
1154    selection: Selection<MultiBufferOffset>,
1155    buffer: &MultiBufferSnapshot,
1156) -> Selection<Anchor> {
1157    let end_bias = if selection.start == selection.end {
1158        Bias::Right
1159    } else {
1160        Bias::Left
1161    };
1162    Selection {
1163        id: selection.id,
1164        start: buffer.anchor_after(selection.start),
1165        end: buffer.anchor_at(selection.end, end_bias),
1166        reversed: selection.reversed,
1167        goal: selection.goal,
1168    }
1169}
1170
1171fn resolve_selections_point<'a>(
1172    selections: impl 'a + IntoIterator<Item = &'a Selection<Anchor>>,
1173    map: &'a DisplaySnapshot,
1174) -> impl 'a + Iterator<Item = Selection<Point>> {
1175    let (to_summarize, selections) = selections.into_iter().tee();
1176    let mut summaries = map
1177        .buffer_snapshot()
1178        .summaries_for_anchors::<Point, _>(to_summarize.flat_map(|s| [&s.start, &s.end]))
1179        .into_iter();
1180    selections.map(move |s| {
1181        let start = summaries.next().unwrap();
1182        let end = summaries.next().unwrap();
1183        assert!(start <= end, "start: {:?}, end: {:?}", start, end);
1184        Selection {
1185            id: s.id,
1186            start,
1187            end,
1188            reversed: s.reversed,
1189            goal: s.goal,
1190        }
1191    })
1192}
1193
1194/// Panics if passed selections are not in order
1195/// Resolves the anchors to display positions
1196fn resolve_selections_display<'a>(
1197    selections: impl 'a + IntoIterator<Item = &'a Selection<Anchor>>,
1198    map: &'a DisplaySnapshot,
1199) -> impl 'a + Iterator<Item = Selection<DisplayPoint>> {
1200    let selections = resolve_selections_point(selections, map).map(move |s| {
1201        let display_start = map.point_to_display_point(s.start, Bias::Left);
1202        let display_end = map.point_to_display_point(
1203            s.end,
1204            if s.start == s.end {
1205                Bias::Right
1206            } else {
1207                Bias::Left
1208            },
1209        );
1210        assert!(
1211            display_start <= display_end,
1212            "display_start: {:?}, display_end: {:?}",
1213            display_start,
1214            display_end
1215        );
1216        Selection {
1217            id: s.id,
1218            start: display_start,
1219            end: display_end,
1220            reversed: s.reversed,
1221            goal: s.goal,
1222        }
1223    });
1224    coalesce_selections(selections)
1225}
1226
1227/// Resolves the passed in anchors to [`MultiBufferDimension`]s `D`
1228/// wrapping around blocks inbetween.
1229///
1230/// # Panics
1231///
1232/// Panics if passed selections are not in order
1233pub(crate) fn resolve_selections_wrapping_blocks<'a, D, I>(
1234    selections: I,
1235    map: &'a DisplaySnapshot,
1236) -> impl 'a + Iterator<Item = Selection<D>>
1237where
1238    D: MultiBufferDimension + Sub + AddAssign<<D as Sub>::Output> + Ord,
1239    I: 'a + IntoIterator<Item = &'a Selection<Anchor>>,
1240{
1241    // Transforms `Anchor -> DisplayPoint -> Point -> DisplayPoint -> D`
1242    // todo(lw): We should be able to short circuit the `Anchor -> DisplayPoint -> Point` to `Anchor -> Point`
1243    let (to_convert, selections) = resolve_selections_display(selections, map).tee();
1244    let mut converted_endpoints =
1245        map.buffer_snapshot()
1246            .dimensions_from_points::<D>(to_convert.flat_map(|s| {
1247                let start = map.display_point_to_point(s.start, Bias::Left);
1248                let end = map.display_point_to_point(s.end, Bias::Right);
1249                assert!(start <= end, "start: {:?}, end: {:?}", start, end);
1250                [start, end]
1251            }));
1252    selections.map(move |s| {
1253        let start = converted_endpoints.next().unwrap();
1254        let end = converted_endpoints.next().unwrap();
1255        assert!(start <= end, "start: {:?}, end: {:?}", start, end);
1256        Selection {
1257            id: s.id,
1258            start,
1259            end,
1260            reversed: s.reversed,
1261            goal: s.goal,
1262        }
1263    })
1264}
1265
1266fn coalesce_selections<D: Ord + fmt::Debug + Copy>(
1267    selections: impl Iterator<Item = Selection<D>>,
1268) -> impl Iterator<Item = Selection<D>> {
1269    let mut selections = selections.peekable();
1270    iter::from_fn(move || {
1271        let mut selection = selections.next()?;
1272        while let Some(next_selection) = selections.peek() {
1273            if should_merge(
1274                selection.start,
1275                selection.end,
1276                next_selection.start,
1277                next_selection.end,
1278                true,
1279            ) {
1280                if selection.reversed == next_selection.reversed {
1281                    selection.end = cmp::max(selection.end, next_selection.end);
1282                    selections.next();
1283                } else {
1284                    selection.end = cmp::max(selection.start, next_selection.start);
1285                    break;
1286                }
1287            } else {
1288                break;
1289            }
1290        }
1291        assert!(
1292            selection.start <= selection.end,
1293            "selection.start: {:?}, selection.end: {:?}, selection.reversed: {:?}",
1294            selection.start,
1295            selection.end,
1296            selection.reversed
1297        );
1298        Some(selection)
1299    })
1300}
1301
1302/// Determines whether two selections should be merged into one.
1303///
1304/// Two selections should be merged when:
1305/// 1. They overlap: the selections share at least one position
1306/// 2. They have the same start position: one contains or equals the other
1307/// 3. A cursor touches a selection boundary: a zero-width selection (cursor) at the
1308///    start or end of another selection should be absorbed into it
1309///
1310/// Note: two selections that merely touch (one ends exactly where the other begins)
1311/// but don't share any positions remain separate, see: https://github.com/zed-industries/zed/issues/24748
1312fn should_merge<T: Ord + Copy>(a_start: T, a_end: T, b_start: T, b_end: T, sorted: bool) -> bool {
1313    let is_overlapping = if sorted {
1314        // When sorted, `a` starts before or at `b`, so overlap means `b` starts before `a` ends
1315        b_start < a_end
1316    } else {
1317        a_start < b_end && b_start < a_end
1318    };
1319
1320    // Selections starting at the same position should always merge (one contains the other)
1321    let same_start = a_start == b_start;
1322
1323    // A cursor (zero-width selection) touching another selection's boundary should merge.
1324    // This handles cases like a cursor at position X merging with a selection that
1325    // starts or ends at X.
1326    let is_cursor_a = a_start == a_end;
1327    let is_cursor_b = b_start == b_end;
1328    let cursor_at_boundary = (is_cursor_a && (a_start == b_start || a_end == b_end))
1329        || (is_cursor_b && (b_start == a_start || b_end == a_end));
1330
1331    is_overlapping || same_start || cursor_at_boundary
1332}