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