selections_collection.rs

   1use std::{
   2    cmp, fmt, iter, mem,
   3    ops::{AddAssign, Deref, DerefMut, Range, Sub},
   4    sync::Arc,
   5};
   6
   7use gpui::Pixels;
   8use itertools::Itertools as _;
   9use language::{Bias, Point, PointUtf16, Selection, SelectionGoal};
  10use multi_buffer::{MultiBufferDimension, MultiBufferOffset};
  11use util::post_inc;
  12
  13use crate::{
  14    Anchor, DisplayPoint, DisplayRow, MultiBufferSnapshot, SelectMode, ToOffset,
  15    display_map::{DisplaySnapshot, ToDisplayPoint},
  16    movement::TextLayoutDetails,
  17};
  18
  19#[derive(Debug, Clone)]
  20pub struct PendingSelection {
  21    selection: Selection<Anchor>,
  22    mode: SelectMode,
  23}
  24
  25#[derive(Debug, Clone)]
  26pub struct SelectionsCollection {
  27    next_selection_id: usize,
  28    line_mode: bool,
  29    /// The non-pending, non-overlapping selections.
  30    /// The [SelectionsCollection::pending] selection could possibly overlap these
  31    disjoint: Arc<[Selection<Anchor>]>,
  32    /// A pending selection, such as when the mouse is being dragged
  33    pending: Option<PendingSelection>,
  34    select_mode: SelectMode,
  35    is_extending: bool,
  36}
  37
  38impl SelectionsCollection {
  39    pub fn new() -> Self {
  40        Self {
  41            next_selection_id: 1,
  42            line_mode: false,
  43            disjoint: Arc::default(),
  44            pending: Some(PendingSelection {
  45                selection: Selection {
  46                    id: 0,
  47                    start: Anchor::Min,
  48                    end: Anchor::Min,
  49                    reversed: false,
  50                    goal: SelectionGoal::None,
  51                },
  52                mode: SelectMode::Character,
  53            }),
  54            select_mode: SelectMode::Character,
  55            is_extending: false,
  56        }
  57    }
  58
  59    pub fn clone_state(&mut self, other: &SelectionsCollection) {
  60        self.next_selection_id = other.next_selection_id;
  61        self.line_mode = other.line_mode;
  62        self.disjoint = other.disjoint.clone();
  63        self.pending.clone_from(&other.pending);
  64    }
  65
  66    pub fn count(&self) -> usize {
  67        let mut count = self.disjoint.len();
  68        if self.pending.is_some() {
  69            count += 1;
  70        }
  71        count
  72    }
  73
  74    /// The non-pending, non-overlapping selections. There could be a pending selection that
  75    /// overlaps these if the mouse is being dragged, etc. This could also be empty if there is a
  76    /// pending selection. Returned as selections over Anchors.
  77    pub fn disjoint_anchors_arc(&self) -> Arc<[Selection<Anchor>]> {
  78        self.disjoint.clone()
  79    }
  80
  81    /// The non-pending, non-overlapping selections. There could be a pending selection that
  82    /// overlaps these if the mouse is being dragged, etc. This could also be empty if there is a
  83    /// pending selection. Returned as selections over Anchors.
  84    pub fn disjoint_anchors(&self) -> &[Selection<Anchor>] {
  85        &self.disjoint
  86    }
  87
  88    pub fn disjoint_anchor_ranges(&self) -> impl Iterator<Item = Range<Anchor>> {
  89        // Mapping the Arc slice would borrow it, whereas indexing captures it.
  90        let disjoint = self.disjoint_anchors_arc();
  91        (0..disjoint.len()).map(move |ix| disjoint[ix].range())
  92    }
  93
  94    /// Non-overlapping selections using anchors, including the pending selection.
  95    pub fn all_anchors(&self, snapshot: &DisplaySnapshot) -> Arc<[Selection<Anchor>]> {
  96        if self.pending.is_none() {
  97            self.disjoint_anchors_arc()
  98        } else {
  99            let all_offset_selections = self.all::<MultiBufferOffset>(snapshot);
 100            all_offset_selections
 101                .into_iter()
 102                .map(|selection| selection_to_anchor_selection(selection, snapshot))
 103                .collect()
 104        }
 105    }
 106
 107    pub fn pending_anchor(&self) -> Option<&Selection<Anchor>> {
 108        self.pending.as_ref().map(|pending| &pending.selection)
 109    }
 110
 111    pub fn pending<D>(&self, snapshot: &DisplaySnapshot) -> Option<Selection<D>>
 112    where
 113        D: MultiBufferDimension + Sub + AddAssign<<D as Sub>::Output> + Ord,
 114    {
 115        resolve_selections_wrapping_blocks(self.pending_anchor(), &snapshot).next()
 116    }
 117
 118    pub(crate) fn pending_mode(&self) -> Option<SelectMode> {
 119        self.pending.as_ref().map(|pending| pending.mode.clone())
 120    }
 121
 122    pub fn all<D>(&self, snapshot: &DisplaySnapshot) -> Vec<Selection<D>>
 123    where
 124        D: MultiBufferDimension + Sub + AddAssign<<D as Sub>::Output> + Ord,
 125    {
 126        let disjoint_anchors = &self.disjoint;
 127        let mut disjoint =
 128            resolve_selections_wrapping_blocks::<D, _>(disjoint_anchors.iter(), &snapshot)
 129                .peekable();
 130        let mut pending_opt = self.pending::<D>(&snapshot);
 131        iter::from_fn(move || {
 132            if let Some(pending) = pending_opt.as_mut() {
 133                while let Some(next_selection) = disjoint.peek() {
 134                    if should_merge(
 135                        pending.start,
 136                        pending.end,
 137                        next_selection.start,
 138                        next_selection.end,
 139                        false,
 140                    ) {
 141                        let next_selection = disjoint.next().unwrap();
 142                        if next_selection.start < pending.start {
 143                            pending.start = next_selection.start;
 144                        }
 145                        if next_selection.end > pending.end {
 146                            pending.end = next_selection.end;
 147                        }
 148                    } else if next_selection.end < pending.start {
 149                        return disjoint.next();
 150                    } else {
 151                        break;
 152                    }
 153                }
 154
 155                pending_opt.take()
 156            } else {
 157                disjoint.next()
 158            }
 159        })
 160        .collect()
 161    }
 162
 163    /// Returns all of the selections, adjusted to take into account the selection line_mode
 164    pub fn all_adjusted(&self, snapshot: &DisplaySnapshot) -> Vec<Selection<Point>> {
 165        let mut selections = self.all::<Point>(&snapshot);
 166        if self.line_mode {
 167            for selection in &mut selections {
 168                let new_range = snapshot.expand_to_line(selection.range());
 169                selection.start = new_range.start;
 170                selection.end = new_range.end;
 171            }
 172        }
 173        selections
 174    }
 175
 176    /// Returns the newest selection, adjusted to take into account the selection line_mode
 177    pub fn newest_adjusted(&self, snapshot: &DisplaySnapshot) -> Selection<Point> {
 178        let mut selection = self.newest::<Point>(&snapshot);
 179        if self.line_mode {
 180            let new_range = snapshot.expand_to_line(selection.range());
 181            selection.start = new_range.start;
 182            selection.end = new_range.end;
 183        }
 184        selection
 185    }
 186
 187    pub fn all_adjusted_display(
 188        &self,
 189        display_map: &DisplaySnapshot,
 190    ) -> Vec<Selection<DisplayPoint>> {
 191        if self.line_mode {
 192            let selections = self.all::<Point>(&display_map);
 193            let result = selections
 194                .into_iter()
 195                .map(|mut selection| {
 196                    let new_range = display_map.expand_to_line(selection.range());
 197                    selection.start = new_range.start;
 198                    selection.end = new_range.end;
 199                    selection.map(|point| point.to_display_point(&display_map))
 200                })
 201                .collect();
 202            result
 203        } else {
 204            self.all_display(display_map)
 205        }
 206    }
 207
 208    pub fn disjoint_in_range<D>(
 209        &self,
 210        range: Range<Anchor>,
 211        snapshot: &DisplaySnapshot,
 212    ) -> Vec<Selection<D>>
 213    where
 214        D: MultiBufferDimension + Sub + AddAssign<<D as Sub>::Output> + Ord + std::fmt::Debug,
 215    {
 216        let start_ix = match self
 217            .disjoint
 218            .binary_search_by(|probe| probe.end.cmp(&range.start, snapshot.buffer_snapshot()))
 219        {
 220            Ok(ix) | Err(ix) => ix,
 221        };
 222        let end_ix = match self
 223            .disjoint
 224            .binary_search_by(|probe| probe.start.cmp(&range.end, snapshot.buffer_snapshot()))
 225        {
 226            Ok(ix) => ix + 1,
 227            Err(ix) => ix,
 228        };
 229        resolve_selections_wrapping_blocks(&self.disjoint[start_ix..end_ix], snapshot).collect()
 230    }
 231
 232    pub fn all_display(&self, snapshot: &DisplaySnapshot) -> Vec<Selection<DisplayPoint>> {
 233        let disjoint_anchors = &self.disjoint;
 234        let mut disjoint =
 235            resolve_selections_display(disjoint_anchors.iter(), &snapshot).peekable();
 236        let mut pending_opt = resolve_selections_display(self.pending_anchor(), &snapshot).next();
 237        iter::from_fn(move || {
 238            if let Some(pending) = pending_opt.as_mut() {
 239                while let Some(next_selection) = disjoint.peek() {
 240                    if should_merge(
 241                        pending.start,
 242                        pending.end,
 243                        next_selection.start,
 244                        next_selection.end,
 245                        false,
 246                    ) {
 247                        let next_selection = disjoint.next().unwrap();
 248                        if next_selection.start < pending.start {
 249                            pending.start = next_selection.start;
 250                        }
 251                        if next_selection.end > pending.end {
 252                            pending.end = next_selection.end;
 253                        }
 254                    } else if next_selection.end < pending.start {
 255                        return disjoint.next();
 256                    } else {
 257                        break;
 258                    }
 259                }
 260
 261                pending_opt.take()
 262            } else {
 263                disjoint.next()
 264            }
 265        })
 266        .collect()
 267    }
 268
 269    pub fn newest_anchor(&self) -> &Selection<Anchor> {
 270        self.pending
 271            .as_ref()
 272            .map(|s| &s.selection)
 273            .or_else(|| self.disjoint.iter().max_by_key(|s| s.id))
 274            .unwrap()
 275    }
 276
 277    pub fn newest<D>(&self, snapshot: &DisplaySnapshot) -> Selection<D>
 278    where
 279        D: MultiBufferDimension + Sub + AddAssign<<D as Sub>::Output> + Ord,
 280    {
 281        resolve_selections_wrapping_blocks([self.newest_anchor()], &snapshot)
 282            .next()
 283            .unwrap()
 284    }
 285
 286    pub fn newest_display(&self, snapshot: &DisplaySnapshot) -> Selection<DisplayPoint> {
 287        resolve_selections_display([self.newest_anchor()], &snapshot)
 288            .next()
 289            .unwrap()
 290    }
 291
 292    pub fn oldest_anchor(&self) -> &Selection<Anchor> {
 293        self.disjoint
 294            .iter()
 295            .min_by_key(|s| s.id)
 296            .or_else(|| self.pending.as_ref().map(|p| &p.selection))
 297            .unwrap()
 298    }
 299
 300    pub fn oldest<D>(&self, snapshot: &DisplaySnapshot) -> Selection<D>
 301    where
 302        D: MultiBufferDimension + Sub + AddAssign<<D as Sub>::Output> + Ord,
 303    {
 304        resolve_selections_wrapping_blocks([self.oldest_anchor()], &snapshot)
 305            .next()
 306            .unwrap()
 307    }
 308
 309    pub fn first_anchor(&self) -> Selection<Anchor> {
 310        self.pending
 311            .as_ref()
 312            .map(|pending| pending.selection.clone())
 313            .unwrap_or_else(|| self.disjoint.first().cloned().unwrap())
 314    }
 315
 316    pub fn first<D>(&self, snapshot: &DisplaySnapshot) -> Selection<D>
 317    where
 318        D: MultiBufferDimension + Sub + AddAssign<<D as Sub>::Output> + Ord,
 319    {
 320        self.all(snapshot).first().unwrap().clone()
 321    }
 322
 323    pub fn last<D>(&self, snapshot: &DisplaySnapshot) -> Selection<D>
 324    where
 325        D: MultiBufferDimension + Sub + AddAssign<<D as Sub>::Output> + Ord,
 326    {
 327        self.all(snapshot).last().unwrap().clone()
 328    }
 329
 330    /// Returns a list of (potentially backwards!) ranges representing the selections.
 331    /// Useful for test assertions, but prefer `.all()` instead.
 332    #[cfg(any(test, feature = "test-support"))]
 333    pub fn ranges<D>(&self, snapshot: &DisplaySnapshot) -> Vec<Range<D>>
 334    where
 335        D: MultiBufferDimension + Sub + AddAssign<<D as Sub>::Output> + Ord,
 336    {
 337        self.all::<D>(snapshot)
 338            .iter()
 339            .map(|s| {
 340                if s.reversed {
 341                    s.end..s.start
 342                } else {
 343                    s.start..s.end
 344                }
 345            })
 346            .collect()
 347    }
 348
 349    #[cfg(any(test, feature = "test-support"))]
 350    pub fn display_ranges(&self, display_snapshot: &DisplaySnapshot) -> Vec<Range<DisplayPoint>> {
 351        self.disjoint_anchors_arc()
 352            .iter()
 353            .chain(self.pending_anchor())
 354            .map(|s| {
 355                if s.reversed {
 356                    s.end.to_display_point(display_snapshot)
 357                        ..s.start.to_display_point(display_snapshot)
 358                } else {
 359                    s.start.to_display_point(display_snapshot)
 360                        ..s.end.to_display_point(display_snapshot)
 361                }
 362            })
 363            .collect()
 364    }
 365
 366    /// Attempts to build a selection in the provided `DisplayRow` within the
 367    /// same range as the provided range of `Pixels`.
 368    /// Returns `None` if the range is not empty but it starts past the line's
 369    /// length, meaning that the line isn't long enough to be contained within
 370    /// part of the provided range.
 371    pub fn build_columnar_selection(
 372        &mut self,
 373        display_map: &DisplaySnapshot,
 374        row: DisplayRow,
 375        positions: &Range<Pixels>,
 376        reversed: bool,
 377        text_layout_details: &TextLayoutDetails,
 378    ) -> Option<Selection<Point>> {
 379        let is_empty = positions.start == positions.end;
 380        let line_len = display_map.line_len(row);
 381        let line = display_map.layout_row(row, text_layout_details);
 382        let start_col = line.closest_index_for_x(positions.start) as u32;
 383
 384        let (start, end) = if is_empty {
 385            let point = DisplayPoint::new(row, std::cmp::min(start_col, line_len));
 386            (point, point)
 387        } else {
 388            if start_col >= line_len {
 389                return None;
 390            }
 391            let start = DisplayPoint::new(row, start_col);
 392            let end_col = line.closest_index_for_x(positions.end) as u32;
 393            let end = DisplayPoint::new(row, end_col);
 394            (start, end)
 395        };
 396
 397        Some(Selection {
 398            id: post_inc(&mut self.next_selection_id),
 399            start: start.to_point(display_map),
 400            end: end.to_point(display_map),
 401            reversed,
 402            goal: SelectionGoal::HorizontalRange {
 403                start: positions.start.into(),
 404                end: positions.end.into(),
 405            },
 406        })
 407    }
 408
 409    /// Attempts to build a selection in the provided buffer row using the
 410    /// same UTF-16 column range as specified.
 411    /// Returns `None` if the range is not empty but it starts past the line's
 412    /// length, meaning that the line isn't long enough to be contained within
 413    /// part of the provided range.
 414    fn build_columnar_selection_from_utf16_columns(
 415        &mut self,
 416        display_map: &DisplaySnapshot,
 417        buffer_row: u32,
 418        positions: &Range<u32>,
 419        reversed: bool,
 420        text_layout_details: &TextLayoutDetails,
 421    ) -> Option<Selection<Point>> {
 422        let snapshot = display_map.buffer_snapshot();
 423        let is_empty = positions.start == positions.end;
 424        let line_len_utf16 = snapshot.line_len_utf16(multi_buffer::MultiBufferRow(buffer_row));
 425
 426        let (start, end) = if is_empty {
 427            let column = std::cmp::min(positions.start, line_len_utf16);
 428            let point = snapshot.point_utf16_to_point(PointUtf16::new(buffer_row, column));
 429            (point, point)
 430        } else {
 431            if positions.start >= line_len_utf16 {
 432                return None;
 433            }
 434
 435            let start = snapshot.point_utf16_to_point(PointUtf16::new(buffer_row, positions.start));
 436            let end_column = std::cmp::min(positions.end, line_len_utf16);
 437            let end = snapshot.point_utf16_to_point(PointUtf16::new(buffer_row, end_column));
 438            (start, end)
 439        };
 440
 441        let start_display_point = start.to_display_point(display_map);
 442        let end_display_point = end.to_display_point(display_map);
 443        let start_x = display_map.x_for_display_point(start_display_point, text_layout_details);
 444        let end_x = display_map.x_for_display_point(end_display_point, text_layout_details);
 445
 446        Some(Selection {
 447            id: post_inc(&mut self.next_selection_id),
 448            start,
 449            end,
 450            reversed,
 451            goal: SelectionGoal::HorizontalRange {
 452                start: start_x.min(end_x).into(),
 453                end: start_x.max(end_x).into(),
 454            },
 455        })
 456    }
 457
 458    /// Finds the next columnar selection by walking display rows one at a time
 459    /// so that soft-wrapped lines are considered and not skipped.
 460    pub fn find_next_columnar_selection_by_display_row(
 461        &mut self,
 462        display_map: &DisplaySnapshot,
 463        start_row: DisplayRow,
 464        end_row: DisplayRow,
 465        above: bool,
 466        positions: &Range<Pixels>,
 467        reversed: bool,
 468        text_layout_details: &TextLayoutDetails,
 469    ) -> Option<Selection<Point>> {
 470        let mut row = start_row;
 471        while row != end_row {
 472            if above {
 473                row.0 -= 1;
 474            } else {
 475                row.0 += 1;
 476            }
 477
 478            if let Some(selection) = self.build_columnar_selection(
 479                display_map,
 480                row,
 481                positions,
 482                reversed,
 483                text_layout_details,
 484            ) {
 485                return Some(selection);
 486            }
 487        }
 488        None
 489    }
 490
 491    /// Finds the next columnar selection by skipping to the next buffer row,
 492    /// ignoring soft-wrapped lines.
 493    pub fn find_next_columnar_selection_by_buffer_row(
 494        &mut self,
 495        display_map: &DisplaySnapshot,
 496        start_row: DisplayRow,
 497        end_row: DisplayRow,
 498        above: bool,
 499        goal_columns: &Range<u32>,
 500        reversed: bool,
 501        text_layout_details: &TextLayoutDetails,
 502    ) -> Option<Selection<Point>> {
 503        let mut row = start_row;
 504        let direction = if above { -1 } else { 1 };
 505        while row != end_row {
 506            let new_row =
 507                display_map.start_of_relative_buffer_row(DisplayPoint::new(row, 0), direction);
 508            row = new_row.row();
 509            let buffer_row = new_row.to_point(display_map).row;
 510
 511            if let Some(selection) = self.build_columnar_selection_from_utf16_columns(
 512                display_map,
 513                buffer_row,
 514                goal_columns,
 515                reversed,
 516                text_layout_details,
 517            ) {
 518                return Some(selection);
 519            }
 520        }
 521        None
 522    }
 523
 524    pub fn change_with<R>(
 525        &mut self,
 526        snapshot: &DisplaySnapshot,
 527        change: impl FnOnce(&mut MutableSelectionsCollection<'_, '_>) -> R,
 528    ) -> (bool, R) {
 529        let mut mutable_collection = MutableSelectionsCollection {
 530            snapshot,
 531            collection: self,
 532            selections_changed: false,
 533        };
 534
 535        let result = change(&mut mutable_collection);
 536        assert!(
 537            !mutable_collection.disjoint.is_empty() || mutable_collection.pending.is_some(),
 538            "There must be at least one selection"
 539        );
 540        if cfg!(debug_assertions) {
 541            mutable_collection.disjoint.iter().for_each(|selection| {
 542                assert!(
 543                     selection.start.cmp(&selection.end, &snapshot).is_le(),
 544                    "disjoint selection has start > end: {:?}",
 545                    mutable_collection.disjoint
 546                );
 547                assert!(
 548                    snapshot.can_resolve(&selection.start),
 549                    "disjoint selection start is not resolvable for the given snapshot:\n{selection:?}",
 550                );
 551                assert!(
 552                    snapshot.can_resolve(&selection.end),
 553                    "disjoint selection start is not resolvable for the given snapshot:\n{selection:?}",
 554                );
 555            });
 556            assert!(
 557                mutable_collection
 558                    .disjoint
 559                    .is_sorted_by(|first, second| first.end.cmp(&second.start, &snapshot).is_le()),
 560                "disjoint selections are not sorted: {:?}",
 561                mutable_collection.disjoint
 562            );
 563            if let Some(pending) = &mutable_collection.pending {
 564                let selection = &pending.selection;
 565                assert!(
 566                    selection.start.cmp(&selection.end, &snapshot).is_le(),
 567                    "pending selection has start > end: {:?}",
 568                    selection
 569                );
 570                assert!(
 571                    snapshot.can_resolve(&selection.start),
 572                    "pending selection start is not resolvable for the given snapshot: {pending:?}",
 573                );
 574                assert!(
 575                    snapshot.can_resolve(&selection.end),
 576                    "pending selection end is not resolvable for the given snapshot: {pending:?}",
 577                );
 578            }
 579        }
 580        (mutable_collection.selections_changed, result)
 581    }
 582
 583    pub fn next_selection_id(&self) -> usize {
 584        self.next_selection_id
 585    }
 586
 587    pub fn line_mode(&self) -> bool {
 588        self.line_mode
 589    }
 590
 591    pub fn set_line_mode(&mut self, line_mode: bool) {
 592        self.line_mode = line_mode;
 593    }
 594
 595    pub fn select_mode(&self) -> &SelectMode {
 596        &self.select_mode
 597    }
 598
 599    pub fn set_select_mode(&mut self, select_mode: SelectMode) {
 600        self.select_mode = select_mode;
 601    }
 602
 603    pub fn is_extending(&self) -> bool {
 604        self.is_extending
 605    }
 606
 607    pub fn set_is_extending(&mut self, is_extending: bool) {
 608        self.is_extending = is_extending;
 609    }
 610}
 611
 612pub struct MutableSelectionsCollection<'snap, 'a> {
 613    collection: &'a mut SelectionsCollection,
 614    snapshot: &'snap DisplaySnapshot,
 615    selections_changed: bool,
 616}
 617
 618impl<'snap, 'a> fmt::Debug for MutableSelectionsCollection<'snap, 'a> {
 619    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 620        f.debug_struct("MutableSelectionsCollection")
 621            .field("collection", &self.collection)
 622            .field("selections_changed", &self.selections_changed)
 623            .finish()
 624    }
 625}
 626
 627impl<'snap, 'a> MutableSelectionsCollection<'snap, 'a> {
 628    pub fn display_snapshot(&self) -> DisplaySnapshot {
 629        self.snapshot.clone()
 630    }
 631
 632    pub fn clear_disjoint(&mut self) {
 633        self.collection.disjoint = Arc::default();
 634    }
 635
 636    pub fn delete(&mut self, selection_id: usize) {
 637        let mut changed = false;
 638        self.collection.disjoint = self
 639            .disjoint
 640            .iter()
 641            .filter(|selection| {
 642                let found = selection.id == selection_id;
 643                changed |= found;
 644                !found
 645            })
 646            .cloned()
 647            .collect();
 648
 649        self.selections_changed |= changed;
 650    }
 651
 652    pub fn remove_selections_from_buffer(&mut self, buffer_id: language::BufferId) {
 653        let mut changed = false;
 654
 655        let filtered_selections: Arc<[Selection<Anchor>]> = {
 656            self.disjoint
 657                .iter()
 658                .filter(|selection| {
 659                    if let Some((selection_buffer_anchor, _)) =
 660                        self.snapshot.anchor_to_buffer_anchor(selection.start)
 661                    {
 662                        let should_remove = selection_buffer_anchor.buffer_id == buffer_id;
 663                        changed |= should_remove;
 664                        !should_remove
 665                    } else {
 666                        true
 667                    }
 668                })
 669                .cloned()
 670                .collect()
 671        };
 672
 673        if filtered_selections.is_empty() {
 674            let buffer_snapshot = self.snapshot.buffer_snapshot();
 675            let anchor = buffer_snapshot
 676                .excerpts()
 677                .find(|excerpt| excerpt.context.start.buffer_id == buffer_id)
 678                .and_then(|excerpt| buffer_snapshot.anchor_in_excerpt(excerpt.context.start))
 679                .unwrap_or_else(|| self.snapshot.anchor_before(MultiBufferOffset(0)));
 680            self.collection.disjoint = Arc::from([Selection {
 681                id: post_inc(&mut self.collection.next_selection_id),
 682                start: anchor,
 683                end: anchor,
 684                reversed: false,
 685                goal: SelectionGoal::None,
 686            }]);
 687        } else {
 688            self.collection.disjoint = filtered_selections;
 689        }
 690
 691        self.selections_changed |= changed;
 692    }
 693
 694    pub fn clear_pending(&mut self) {
 695        if self.collection.pending.is_some() {
 696            self.collection.pending = None;
 697            self.selections_changed = true;
 698        }
 699    }
 700
 701    pub(crate) fn set_pending_anchor_range(&mut self, range: Range<Anchor>, mode: SelectMode) {
 702        self.collection.pending = Some(PendingSelection {
 703            selection: {
 704                let mut start = range.start;
 705                let mut end = range.end;
 706                let reversed = if start.cmp(&end, self.snapshot).is_gt() {
 707                    mem::swap(&mut start, &mut end);
 708                    true
 709                } else {
 710                    false
 711                };
 712                Selection {
 713                    id: post_inc(&mut self.collection.next_selection_id),
 714                    start,
 715                    end,
 716                    reversed,
 717                    goal: SelectionGoal::None,
 718                }
 719            },
 720            mode,
 721        });
 722        self.selections_changed = true;
 723    }
 724
 725    pub(crate) fn set_pending(&mut self, selection: Selection<Anchor>, mode: SelectMode) {
 726        self.collection.pending = Some(PendingSelection { selection, mode });
 727        self.selections_changed = true;
 728    }
 729
 730    pub fn try_cancel(&mut self) -> bool {
 731        if let Some(pending) = self.collection.pending.take() {
 732            if self.disjoint.is_empty() {
 733                self.collection.disjoint = Arc::from([pending.selection]);
 734            }
 735            self.selections_changed = true;
 736            return true;
 737        }
 738
 739        let mut oldest = self.oldest_anchor().clone();
 740        if self.count() > 1 {
 741            self.collection.disjoint = Arc::from([oldest]);
 742            self.selections_changed = true;
 743            return true;
 744        }
 745
 746        if !oldest.start.cmp(&oldest.end, self.snapshot).is_eq() {
 747            let head = oldest.head();
 748            oldest.start = head;
 749            oldest.end = head;
 750            self.collection.disjoint = Arc::from([oldest]);
 751            self.selections_changed = true;
 752            return true;
 753        }
 754
 755        false
 756    }
 757
 758    pub fn insert_range<T>(&mut self, range: Range<T>)
 759    where
 760        T: ToOffset,
 761    {
 762        let display_map = self.display_snapshot();
 763        let mut selections = self.collection.all(&display_map);
 764        let mut start = range.start.to_offset(self.snapshot);
 765        let mut end = range.end.to_offset(self.snapshot);
 766        let reversed = if start > end {
 767            mem::swap(&mut start, &mut end);
 768            true
 769        } else {
 770            false
 771        };
 772        selections.push(Selection {
 773            id: post_inc(&mut self.collection.next_selection_id),
 774            start,
 775            end,
 776            reversed,
 777            goal: SelectionGoal::None,
 778        });
 779        self.select(selections);
 780    }
 781
 782    pub fn select<T>(&mut self, selections: Vec<Selection<T>>)
 783    where
 784        T: ToOffset + std::marker::Copy + std::fmt::Debug,
 785    {
 786        let mut selections = selections
 787            .into_iter()
 788            .map(|selection| selection.map(|it| it.to_offset(self.snapshot)))
 789            .map(|mut selection| {
 790                if selection.start > selection.end {
 791                    mem::swap(&mut selection.start, &mut selection.end);
 792                    selection.reversed = true
 793                }
 794                selection
 795            })
 796            .collect::<Vec<_>>();
 797        selections.sort_unstable_by_key(|s| s.start);
 798
 799        let mut i = 1;
 800        while i < selections.len() {
 801            let prev = &selections[i - 1];
 802            let current = &selections[i];
 803
 804            if should_merge(prev.start, prev.end, current.start, current.end, true) {
 805                let removed = selections.remove(i);
 806                if removed.start < selections[i - 1].start {
 807                    selections[i - 1].start = removed.start;
 808                }
 809                if selections[i - 1].end < removed.end {
 810                    selections[i - 1].end = removed.end;
 811                }
 812            } else {
 813                i += 1;
 814            }
 815        }
 816
 817        self.collection.disjoint = Arc::from_iter(
 818            selections
 819                .into_iter()
 820                .map(|selection| selection_to_anchor_selection(selection, self.snapshot)),
 821        );
 822        self.collection.pending = None;
 823        self.selections_changed = true;
 824    }
 825
 826    pub fn select_anchors(&mut self, selections: Vec<Selection<Anchor>>) {
 827        let map = self.display_snapshot();
 828        let resolved_selections =
 829            resolve_selections_wrapping_blocks::<MultiBufferOffset, _>(&selections, &map)
 830                .collect::<Vec<_>>();
 831        self.select(resolved_selections);
 832    }
 833
 834    pub fn select_ranges<I, T>(&mut self, ranges: I)
 835    where
 836        I: IntoIterator<Item = Range<T>>,
 837        T: ToOffset,
 838    {
 839        let ranges = ranges
 840            .into_iter()
 841            .map(|range| range.start.to_offset(self.snapshot)..range.end.to_offset(self.snapshot));
 842        self.select_offset_ranges(ranges);
 843    }
 844
 845    fn select_offset_ranges<I>(&mut self, ranges: I)
 846    where
 847        I: IntoIterator<Item = Range<MultiBufferOffset>>,
 848    {
 849        let selections = ranges
 850            .into_iter()
 851            .map(|range| {
 852                let mut start = range.start;
 853                let mut end = range.end;
 854                let reversed = if start > end {
 855                    mem::swap(&mut start, &mut end);
 856                    true
 857                } else {
 858                    false
 859                };
 860                Selection {
 861                    id: post_inc(&mut self.collection.next_selection_id),
 862                    start,
 863                    end,
 864                    reversed,
 865                    goal: SelectionGoal::None,
 866                }
 867            })
 868            .collect::<Vec<_>>();
 869
 870        self.select(selections)
 871    }
 872
 873    pub fn select_anchor_ranges<I>(&mut self, ranges: I)
 874    where
 875        I: IntoIterator<Item = Range<Anchor>>,
 876    {
 877        let selections = ranges
 878            .into_iter()
 879            .map(|range| {
 880                let mut start = range.start;
 881                let mut end = range.end;
 882                let reversed = if start.cmp(&end, self.snapshot).is_gt() {
 883                    mem::swap(&mut start, &mut end);
 884                    true
 885                } else {
 886                    false
 887                };
 888                Selection {
 889                    id: post_inc(&mut self.collection.next_selection_id),
 890                    start,
 891                    end,
 892                    reversed,
 893                    goal: SelectionGoal::None,
 894                }
 895            })
 896            .collect::<Vec<_>>();
 897        self.select_anchors(selections)
 898    }
 899
 900    pub fn new_selection_id(&mut self) -> usize {
 901        post_inc(&mut self.next_selection_id)
 902    }
 903
 904    pub fn select_display_ranges<T>(&mut self, ranges: T)
 905    where
 906        T: IntoIterator<Item = Range<DisplayPoint>>,
 907    {
 908        let selections = ranges
 909            .into_iter()
 910            .map(|range| {
 911                let mut start = range.start;
 912                let mut end = range.end;
 913                let reversed = if start > end {
 914                    mem::swap(&mut start, &mut end);
 915                    true
 916                } else {
 917                    false
 918                };
 919                Selection {
 920                    id: post_inc(&mut self.collection.next_selection_id),
 921                    start: start.to_point(self.snapshot),
 922                    end: end.to_point(self.snapshot),
 923                    reversed,
 924                    goal: SelectionGoal::None,
 925                }
 926            })
 927            .collect();
 928        self.select(selections);
 929    }
 930
 931    pub fn reverse_selections(&mut self) {
 932        let mut new_selections: Vec<Selection<Point>> = Vec::new();
 933        let disjoint = self.disjoint.clone();
 934        for selection in disjoint
 935            .iter()
 936            .sorted_by(|first, second| Ord::cmp(&second.id, &first.id))
 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        move_selection: &mut dyn 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        move_selection: &mut dyn 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        update_head: &mut dyn FnMut(
1007            &DisplaySnapshot,
1008            DisplayPoint,
1009            SelectionGoal,
1010        ) -> (DisplayPoint, SelectionGoal),
1011    ) {
1012        self.move_with(&mut |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        update_cursor_position: &mut dyn FnMut(
1021            &DisplaySnapshot,
1022            DisplayPoint,
1023            SelectionGoal,
1024        ) -> (DisplayPoint, SelectionGoal),
1025    ) {
1026        self.move_with(&mut |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        update_cursor_position: &mut dyn FnMut(
1035            &DisplaySnapshot,
1036            DisplayPoint,
1037            SelectionGoal,
1038        ) -> Option<(DisplayPoint, SelectionGoal)>,
1039    ) {
1040        self.move_cursors_with(&mut |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    pub fn pending_anchor_mut(&mut self) -> Option<&mut Selection<Anchor>> {
1066        self.selections_changed = true;
1067        self.pending.as_mut().map(|pending| &mut pending.selection)
1068    }
1069}
1070
1071impl Deref for MutableSelectionsCollection<'_, '_> {
1072    type Target = SelectionsCollection;
1073    fn deref(&self) -> &Self::Target {
1074        self.collection
1075    }
1076}
1077
1078impl DerefMut for MutableSelectionsCollection<'_, '_> {
1079    fn deref_mut(&mut self) -> &mut Self::Target {
1080        self.collection
1081    }
1082}
1083
1084fn selection_to_anchor_selection(
1085    selection: Selection<MultiBufferOffset>,
1086    buffer: &MultiBufferSnapshot,
1087) -> Selection<Anchor> {
1088    let end_bias = if selection.start == selection.end {
1089        Bias::Right
1090    } else {
1091        Bias::Left
1092    };
1093    Selection {
1094        id: selection.id,
1095        start: buffer.anchor_after(selection.start),
1096        end: buffer.anchor_at(selection.end, end_bias),
1097        reversed: selection.reversed,
1098        goal: selection.goal,
1099    }
1100}
1101
1102fn resolve_selections_point<'a>(
1103    selections: impl 'a + IntoIterator<Item = &'a Selection<Anchor>>,
1104    map: &'a DisplaySnapshot,
1105) -> impl 'a + Iterator<Item = Selection<Point>> {
1106    let (to_summarize, selections) = selections.into_iter().tee();
1107    let mut summaries = map
1108        .buffer_snapshot()
1109        .summaries_for_anchors::<Point, _>(to_summarize.flat_map(|s| [&s.start, &s.end]))
1110        .into_iter();
1111    selections.map(move |s| {
1112        let start = summaries.next().unwrap();
1113        let end = summaries.next().unwrap();
1114        assert!(
1115            start <= end,
1116            "anchors: start: {:?}, end: {:?}; resolved to: start: {:?}, end: {:?}",
1117            s.start,
1118            s.end,
1119            start,
1120            end
1121        );
1122        Selection {
1123            id: s.id,
1124            start,
1125            end,
1126            reversed: s.reversed,
1127            goal: s.goal,
1128        }
1129    })
1130}
1131
1132/// Panics if passed selections are not in order
1133/// Resolves the anchors to display positions
1134fn resolve_selections_display<'a>(
1135    selections: impl 'a + IntoIterator<Item = &'a Selection<Anchor>>,
1136    map: &'a DisplaySnapshot,
1137) -> impl 'a + Iterator<Item = Selection<DisplayPoint>> {
1138    let selections = resolve_selections_point(selections, map).map(move |s| {
1139        let display_start = map.point_to_display_point(s.start, Bias::Left);
1140        let display_end = map.point_to_display_point(
1141            s.end,
1142            if s.start == s.end {
1143                Bias::Right
1144            } else {
1145                Bias::Left
1146            },
1147        );
1148        assert!(
1149            display_start <= display_end,
1150            "display_start: {:?}, display_end: {:?}",
1151            display_start,
1152            display_end
1153        );
1154        Selection {
1155            id: s.id,
1156            start: display_start,
1157            end: display_end,
1158            reversed: s.reversed,
1159            goal: s.goal,
1160        }
1161    });
1162    coalesce_selections(selections)
1163}
1164
1165/// Resolves the passed in anchors to [`MultiBufferDimension`]s `D`
1166/// wrapping around blocks inbetween.
1167///
1168/// # Panics
1169///
1170/// Panics if passed selections are not in order
1171pub(crate) fn resolve_selections_wrapping_blocks<'a, D, I>(
1172    selections: I,
1173    map: &'a DisplaySnapshot,
1174) -> impl 'a + Iterator<Item = Selection<D>>
1175where
1176    D: MultiBufferDimension + Sub + AddAssign<<D as Sub>::Output> + Ord,
1177    I: 'a + IntoIterator<Item = &'a Selection<Anchor>>,
1178{
1179    // Transforms `Anchor -> DisplayPoint -> Point -> DisplayPoint -> D`
1180    // todo(lw): We should be able to short circuit the `Anchor -> DisplayPoint -> Point` to `Anchor -> Point`
1181    let (to_convert, selections) = resolve_selections_display(selections, map).tee();
1182    let mut converted_endpoints =
1183        map.buffer_snapshot()
1184            .dimensions_from_points::<D>(to_convert.flat_map(|s| {
1185                let start = map.display_point_to_point(s.start, Bias::Left);
1186                let end = map.display_point_to_point(s.end, Bias::Right);
1187                assert!(start <= end, "start: {:?}, end: {:?}", start, end);
1188                [start, end]
1189            }));
1190    selections.map(move |s| {
1191        let start = converted_endpoints.next().unwrap();
1192        let end = converted_endpoints.next().unwrap();
1193        assert!(start <= end, "start: {:?}, end: {:?}", start, end);
1194        Selection {
1195            id: s.id,
1196            start,
1197            end,
1198            reversed: s.reversed,
1199            goal: s.goal,
1200        }
1201    })
1202}
1203
1204fn coalesce_selections<D: Ord + fmt::Debug + Copy>(
1205    selections: impl Iterator<Item = Selection<D>>,
1206) -> impl Iterator<Item = Selection<D>> {
1207    let mut selections = selections.peekable();
1208    iter::from_fn(move || {
1209        let mut selection = selections.next()?;
1210        while let Some(next_selection) = selections.peek() {
1211            if should_merge(
1212                selection.start,
1213                selection.end,
1214                next_selection.start,
1215                next_selection.end,
1216                true,
1217            ) {
1218                if selection.reversed == next_selection.reversed {
1219                    selection.end = cmp::max(selection.end, next_selection.end);
1220                    selections.next();
1221                } else {
1222                    selection.end = cmp::max(selection.start, next_selection.start);
1223                    break;
1224                }
1225            } else {
1226                break;
1227            }
1228        }
1229        assert!(
1230            selection.start <= selection.end,
1231            "selection.start: {:?}, selection.end: {:?}, selection.reversed: {:?}",
1232            selection.start,
1233            selection.end,
1234            selection.reversed
1235        );
1236        Some(selection)
1237    })
1238}
1239
1240/// Determines whether two selections should be merged into one.
1241///
1242/// Two selections should be merged when:
1243/// 1. They overlap: the selections share at least one position
1244/// 2. They have the same start position: one contains or equals the other
1245/// 3. A cursor touches a selection boundary: a zero-width selection (cursor) at the
1246///    start or end of another selection should be absorbed into it
1247///
1248/// Note: two selections that merely touch (one ends exactly where the other begins)
1249/// but don't share any positions remain separate, see: https://github.com/zed-industries/zed/issues/24748
1250fn should_merge<T: Ord + Copy>(a_start: T, a_end: T, b_start: T, b_end: T, sorted: bool) -> bool {
1251    let is_overlapping = if sorted {
1252        // When sorted, `a` starts before or at `b`, so overlap means `b` starts before `a` ends
1253        b_start < a_end
1254    } else {
1255        a_start < b_end && b_start < a_end
1256    };
1257
1258    // Selections starting at the same position should always merge (one contains the other)
1259    let same_start = a_start == b_start;
1260
1261    // A cursor (zero-width selection) touching another selection's boundary should merge.
1262    // This handles cases like a cursor at position X merging with a selection that
1263    // starts or ends at X.
1264    let is_cursor_a = a_start == a_end;
1265    let is_cursor_b = b_start == b_end;
1266    let cursor_at_boundary = (is_cursor_a && (a_start == b_start || a_end == b_end))
1267        || (is_cursor_b && (b_start == a_start || b_end == a_end));
1268
1269    is_overlapping || same_start || cursor_at_boundary
1270}