multi_buffer.rs

   1mod anchor;
   2
   3pub use anchor::{Anchor, AnchorRangeExt, Offset};
   4use anyhow::{anyhow, Result};
   5use clock::ReplicaId;
   6use collections::{BTreeMap, Bound, HashMap, HashSet};
   7use futures::{channel::mpsc, SinkExt};
   8use gpui::{AppContext, EntityId, EventEmitter, Model, ModelContext, Task};
   9use itertools::Itertools;
  10use language::{
  11    language_settings::{language_settings, LanguageSettings},
  12    AutoindentMode, Buffer, BufferChunks, BufferRow, BufferSnapshot, Capability, CharClassifier,
  13    CharKind, Chunk, CursorShape, DiagnosticEntry, DiskState, File, IndentGuide, IndentSize,
  14    Language, LanguageScope, OffsetRangeExt, OffsetUtf16, Outline, OutlineItem, Point, PointUtf16,
  15    Selection, TextDimension, ToOffset as _, ToOffsetUtf16 as _, ToPoint as _, ToPointUtf16 as _,
  16    TransactionId, Unclipped,
  17};
  18use smallvec::SmallVec;
  19use std::{
  20    any::type_name,
  21    borrow::Cow,
  22    cell::{Ref, RefCell},
  23    cmp, fmt,
  24    future::Future,
  25    io,
  26    iter::{self, FromIterator},
  27    mem,
  28    ops::{Range, RangeBounds, Sub},
  29    str,
  30    sync::Arc,
  31    time::{Duration, Instant},
  32};
  33use sum_tree::{Bias, Cursor, SumTree};
  34use text::{
  35    locator::Locator,
  36    subscription::{Subscription, Topic},
  37    BufferId, Edit, TextSummary,
  38};
  39use theme::SyntaxTheme;
  40
  41use util::post_inc;
  42
  43#[cfg(any(test, feature = "test-support"))]
  44use gpui::Context;
  45
  46const NEWLINES: &[u8] = &[b'\n'; u8::MAX as usize];
  47
  48#[derive(Debug, Default, Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)]
  49pub struct ExcerptId(usize);
  50
  51impl From<ExcerptId> for EntityId {
  52    fn from(id: ExcerptId) -> Self {
  53        EntityId::from(id.0 as u64)
  54    }
  55}
  56
  57/// One or more [`Buffers`](Buffer) being edited in a single view.
  58///
  59/// See <https://zed.dev/features#multi-buffers>
  60pub struct MultiBuffer {
  61    /// A snapshot of the [`Excerpt`]s in the MultiBuffer.
  62    /// Use [`MultiBuffer::snapshot`] to get a up-to-date snapshot.
  63    snapshot: RefCell<MultiBufferSnapshot>,
  64    /// Contains the state of the buffers being edited
  65    buffers: RefCell<HashMap<BufferId, BufferState>>,
  66    subscriptions: Topic,
  67    /// If true, the multi-buffer only contains a single [`Buffer`] and a single [`Excerpt`]
  68    singleton: bool,
  69    history: History,
  70    title: Option<String>,
  71    capability: Capability,
  72}
  73
  74#[derive(Clone, Debug, PartialEq, Eq)]
  75pub enum Event {
  76    ExcerptsAdded {
  77        buffer: Model<Buffer>,
  78        predecessor: ExcerptId,
  79        excerpts: Vec<(ExcerptId, ExcerptRange<language::Anchor>)>,
  80    },
  81    ExcerptsRemoved {
  82        ids: Vec<ExcerptId>,
  83    },
  84    ExcerptsExpanded {
  85        ids: Vec<ExcerptId>,
  86    },
  87    ExcerptsEdited {
  88        ids: Vec<ExcerptId>,
  89    },
  90    Edited {
  91        singleton_buffer_edited: bool,
  92    },
  93    TransactionUndone {
  94        transaction_id: TransactionId,
  95    },
  96    Reloaded,
  97    ReloadNeeded,
  98    DiffBaseChanged,
  99    DiffUpdated {
 100        buffer: Model<Buffer>,
 101    },
 102    LanguageChanged(BufferId),
 103    CapabilityChanged,
 104    Reparsed(BufferId),
 105    Saved,
 106    FileHandleChanged,
 107    Closed,
 108    Discarded,
 109    DirtyChanged,
 110    DiagnosticsUpdated,
 111}
 112
 113/// A diff hunk, representing a range of consequent lines in a multibuffer.
 114#[derive(Debug, Clone, PartialEq, Eq)]
 115pub struct MultiBufferDiffHunk {
 116    /// The row range in the multibuffer where this diff hunk appears.
 117    pub row_range: Range<MultiBufferRow>,
 118    /// The buffer ID that this hunk belongs to.
 119    pub buffer_id: BufferId,
 120    /// The range of the underlying buffer that this hunk corresponds to.
 121    pub buffer_range: Range<text::Anchor>,
 122    /// The range within the buffer's diff base that this hunk corresponds to.
 123    pub diff_base_byte_range: Range<usize>,
 124}
 125
 126pub type MultiBufferPoint = Point;
 127
 128#[derive(Copy, Clone, Debug, Default, Eq, Ord, PartialOrd, PartialEq, Hash, serde::Deserialize)]
 129#[serde(transparent)]
 130pub struct MultiBufferRow(pub u32);
 131
 132impl MultiBufferRow {
 133    pub const MIN: Self = Self(0);
 134    pub const MAX: Self = Self(u32::MAX);
 135}
 136
 137#[derive(Clone)]
 138struct History {
 139    next_transaction_id: TransactionId,
 140    undo_stack: Vec<Transaction>,
 141    redo_stack: Vec<Transaction>,
 142    transaction_depth: usize,
 143    group_interval: Duration,
 144}
 145
 146#[derive(Clone)]
 147struct Transaction {
 148    id: TransactionId,
 149    buffer_transactions: HashMap<BufferId, text::TransactionId>,
 150    first_edit_at: Instant,
 151    last_edit_at: Instant,
 152    suppress_grouping: bool,
 153}
 154
 155pub trait ToOffset: 'static + fmt::Debug {
 156    fn to_offset(&self, snapshot: &MultiBufferSnapshot) -> usize;
 157}
 158
 159pub trait ToOffsetUtf16: 'static + fmt::Debug {
 160    fn to_offset_utf16(&self, snapshot: &MultiBufferSnapshot) -> OffsetUtf16;
 161}
 162
 163pub trait ToPoint: 'static + fmt::Debug {
 164    fn to_point(&self, snapshot: &MultiBufferSnapshot) -> Point;
 165}
 166
 167pub trait ToPointUtf16: 'static + fmt::Debug {
 168    fn to_point_utf16(&self, snapshot: &MultiBufferSnapshot) -> PointUtf16;
 169}
 170
 171struct BufferState {
 172    buffer: Model<Buffer>,
 173    last_version: clock::Global,
 174    last_non_text_state_update_count: usize,
 175    excerpts: Vec<Locator>,
 176    _subscriptions: [gpui::Subscription; 2],
 177}
 178
 179/// The contents of a [`MultiBuffer`] at a single point in time.
 180#[derive(Clone, Default)]
 181pub struct MultiBufferSnapshot {
 182    singleton: bool,
 183    excerpts: SumTree<Excerpt>,
 184    excerpt_ids: SumTree<ExcerptIdMapping>,
 185    trailing_excerpt_update_count: usize,
 186    non_text_state_update_count: usize,
 187    edit_count: usize,
 188    is_dirty: bool,
 189    has_deleted_file: bool,
 190    has_conflict: bool,
 191    show_headers: bool,
 192}
 193
 194#[derive(Clone)]
 195pub struct ExcerptInfo {
 196    pub id: ExcerptId,
 197    pub buffer: BufferSnapshot,
 198    pub buffer_id: BufferId,
 199    pub range: ExcerptRange<text::Anchor>,
 200}
 201
 202impl std::fmt::Debug for ExcerptInfo {
 203    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 204        f.debug_struct(type_name::<Self>())
 205            .field("id", &self.id)
 206            .field("buffer_id", &self.buffer_id)
 207            .field("path", &self.buffer.file().map(|f| f.path()))
 208            .field("range", &self.range)
 209            .finish()
 210    }
 211}
 212
 213/// A boundary between [`Excerpt`]s in a [`MultiBuffer`]
 214#[derive(Debug)]
 215pub struct ExcerptBoundary {
 216    pub prev: Option<ExcerptInfo>,
 217    pub next: Option<ExcerptInfo>,
 218    /// The row in the `MultiBuffer` where the boundary is located
 219    pub row: MultiBufferRow,
 220}
 221
 222impl ExcerptBoundary {
 223    pub fn starts_new_buffer(&self) -> bool {
 224        match (self.prev.as_ref(), self.next.as_ref()) {
 225            (None, _) => true,
 226            (Some(_), None) => false,
 227            (Some(prev), Some(next)) => prev.buffer_id != next.buffer_id,
 228        }
 229    }
 230}
 231
 232/// A slice into a [`Buffer`] that is being edited in a [`MultiBuffer`].
 233#[derive(Clone)]
 234struct Excerpt {
 235    /// The unique identifier for this excerpt
 236    id: ExcerptId,
 237    /// The location of the excerpt in the [`MultiBuffer`]
 238    locator: Locator,
 239    /// The buffer being excerpted
 240    buffer_id: BufferId,
 241    /// A snapshot of the buffer being excerpted
 242    buffer: BufferSnapshot,
 243    /// The range of the buffer to be shown in the excerpt
 244    range: ExcerptRange<text::Anchor>,
 245    /// The last row in the excerpted slice of the buffer
 246    max_buffer_row: BufferRow,
 247    /// A summary of the text in the excerpt
 248    text_summary: TextSummary,
 249    has_trailing_newline: bool,
 250}
 251
 252/// A public view into an [`Excerpt`] in a [`MultiBuffer`].
 253///
 254/// Contains methods for getting the [`Buffer`] of the excerpt,
 255/// as well as mapping offsets to/from buffer and multibuffer coordinates.
 256#[derive(Clone)]
 257pub struct MultiBufferExcerpt<'a> {
 258    excerpt: &'a Excerpt,
 259    excerpt_offset: usize,
 260}
 261
 262#[derive(Clone, Debug)]
 263struct ExcerptIdMapping {
 264    id: ExcerptId,
 265    locator: Locator,
 266}
 267
 268/// A range of text from a single [`Buffer`], to be shown as an [`Excerpt`].
 269/// These ranges are relative to the buffer itself
 270#[derive(Clone, Debug, Eq, PartialEq)]
 271pub struct ExcerptRange<T> {
 272    /// The full range of text to be shown in the excerpt.
 273    pub context: Range<T>,
 274    /// The primary range of text to be highlighted in the excerpt.
 275    /// In a multi-buffer search, this would be the text that matched the search
 276    pub primary: Option<Range<T>>,
 277}
 278
 279#[derive(Clone, Debug, Default)]
 280pub struct ExcerptSummary {
 281    excerpt_id: ExcerptId,
 282    /// The location of the last [`Excerpt`] being summarized
 283    excerpt_locator: Locator,
 284    /// The maximum row of the [`Excerpt`]s being summarized
 285    max_buffer_row: MultiBufferRow,
 286    text: TextSummary,
 287}
 288
 289#[derive(Clone)]
 290pub struct MultiBufferRows<'a> {
 291    buffer_row_range: Range<u32>,
 292    excerpts: Cursor<'a, Excerpt, Point>,
 293}
 294
 295pub struct MultiBufferChunks<'a> {
 296    range: Range<usize>,
 297    excerpts: Cursor<'a, Excerpt, usize>,
 298    excerpt_chunks: Option<ExcerptChunks<'a>>,
 299    language_aware: bool,
 300}
 301
 302pub struct MultiBufferBytes<'a> {
 303    range: Range<usize>,
 304    excerpts: Cursor<'a, Excerpt, usize>,
 305    excerpt_bytes: Option<ExcerptBytes<'a>>,
 306    chunk: &'a [u8],
 307}
 308
 309pub struct ReversedMultiBufferBytes<'a> {
 310    range: Range<usize>,
 311    excerpts: Cursor<'a, Excerpt, usize>,
 312    excerpt_bytes: Option<ExcerptBytes<'a>>,
 313    chunk: &'a [u8],
 314}
 315
 316struct ExcerptChunks<'a> {
 317    excerpt_id: ExcerptId,
 318    content_chunks: BufferChunks<'a>,
 319    footer_height: usize,
 320}
 321
 322struct ExcerptBytes<'a> {
 323    content_bytes: text::Bytes<'a>,
 324    padding_height: usize,
 325    reversed: bool,
 326}
 327
 328struct BufferEdit {
 329    range: Range<usize>,
 330    new_text: Arc<str>,
 331    is_insertion: bool,
 332    original_indent_column: u32,
 333}
 334
 335#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
 336pub enum ExpandExcerptDirection {
 337    Up,
 338    Down,
 339    UpAndDown,
 340}
 341
 342impl ExpandExcerptDirection {
 343    pub fn should_expand_up(&self) -> bool {
 344        match self {
 345            ExpandExcerptDirection::Up => true,
 346            ExpandExcerptDirection::Down => false,
 347            ExpandExcerptDirection::UpAndDown => true,
 348        }
 349    }
 350
 351    pub fn should_expand_down(&self) -> bool {
 352        match self {
 353            ExpandExcerptDirection::Up => false,
 354            ExpandExcerptDirection::Down => true,
 355            ExpandExcerptDirection::UpAndDown => true,
 356        }
 357    }
 358}
 359
 360#[derive(Clone, Debug, PartialEq)]
 361pub struct MultiBufferIndentGuide {
 362    pub multibuffer_row_range: Range<MultiBufferRow>,
 363    pub buffer: IndentGuide,
 364}
 365
 366impl std::ops::Deref for MultiBufferIndentGuide {
 367    type Target = IndentGuide;
 368
 369    fn deref(&self) -> &Self::Target {
 370        &self.buffer
 371    }
 372}
 373
 374impl MultiBuffer {
 375    pub fn new(capability: Capability) -> Self {
 376        Self {
 377            snapshot: RefCell::new(MultiBufferSnapshot {
 378                show_headers: true,
 379                ..MultiBufferSnapshot::default()
 380            }),
 381            buffers: RefCell::default(),
 382            subscriptions: Topic::default(),
 383            singleton: false,
 384            capability,
 385            title: None,
 386            history: History {
 387                next_transaction_id: clock::Lamport::default(),
 388                undo_stack: Vec::new(),
 389                redo_stack: Vec::new(),
 390                transaction_depth: 0,
 391                group_interval: Duration::from_millis(300),
 392            },
 393        }
 394    }
 395
 396    pub fn without_headers(capability: Capability) -> Self {
 397        Self {
 398            snapshot: Default::default(),
 399            buffers: Default::default(),
 400            subscriptions: Default::default(),
 401            singleton: false,
 402            capability,
 403            history: History {
 404                next_transaction_id: Default::default(),
 405                undo_stack: Default::default(),
 406                redo_stack: Default::default(),
 407                transaction_depth: 0,
 408                group_interval: Duration::from_millis(300),
 409            },
 410            title: Default::default(),
 411        }
 412    }
 413
 414    pub fn clone(&self, new_cx: &mut ModelContext<Self>) -> Self {
 415        let mut buffers = HashMap::default();
 416        for (buffer_id, buffer_state) in self.buffers.borrow().iter() {
 417            buffers.insert(
 418                *buffer_id,
 419                BufferState {
 420                    buffer: buffer_state.buffer.clone(),
 421                    last_version: buffer_state.last_version.clone(),
 422                    last_non_text_state_update_count: buffer_state.last_non_text_state_update_count,
 423                    excerpts: buffer_state.excerpts.clone(),
 424                    _subscriptions: [
 425                        new_cx.observe(&buffer_state.buffer, |_, _, cx| cx.notify()),
 426                        new_cx.subscribe(&buffer_state.buffer, Self::on_buffer_event),
 427                    ],
 428                },
 429            );
 430        }
 431        Self {
 432            snapshot: RefCell::new(self.snapshot.borrow().clone()),
 433            buffers: RefCell::new(buffers),
 434            subscriptions: Default::default(),
 435            singleton: self.singleton,
 436            capability: self.capability,
 437            history: self.history.clone(),
 438            title: self.title.clone(),
 439        }
 440    }
 441
 442    pub fn with_title(mut self, title: String) -> Self {
 443        self.title = Some(title);
 444        self
 445    }
 446
 447    pub fn read_only(&self) -> bool {
 448        self.capability == Capability::ReadOnly
 449    }
 450
 451    pub fn singleton(buffer: Model<Buffer>, cx: &mut ModelContext<Self>) -> Self {
 452        let mut this = Self::new(buffer.read(cx).capability());
 453        this.singleton = true;
 454        this.push_excerpts(
 455            buffer,
 456            [ExcerptRange {
 457                context: text::Anchor::MIN..text::Anchor::MAX,
 458                primary: None,
 459            }],
 460            cx,
 461        );
 462        this.snapshot.borrow_mut().singleton = true;
 463        this
 464    }
 465
 466    /// Returns an up-to-date snapshot of the MultiBuffer.
 467    pub fn snapshot(&self, cx: &AppContext) -> MultiBufferSnapshot {
 468        self.sync(cx);
 469        self.snapshot.borrow().clone()
 470    }
 471
 472    pub fn read(&self, cx: &AppContext) -> Ref<MultiBufferSnapshot> {
 473        self.sync(cx);
 474        self.snapshot.borrow()
 475    }
 476
 477    pub fn as_singleton(&self) -> Option<Model<Buffer>> {
 478        if self.singleton {
 479            return Some(
 480                self.buffers
 481                    .borrow()
 482                    .values()
 483                    .next()
 484                    .unwrap()
 485                    .buffer
 486                    .clone(),
 487            );
 488        } else {
 489            None
 490        }
 491    }
 492
 493    pub fn is_singleton(&self) -> bool {
 494        self.singleton
 495    }
 496
 497    pub fn subscribe(&mut self) -> Subscription {
 498        self.subscriptions.subscribe()
 499    }
 500
 501    pub fn is_dirty(&self, cx: &AppContext) -> bool {
 502        self.read(cx).is_dirty()
 503    }
 504
 505    pub fn has_deleted_file(&self, cx: &AppContext) -> bool {
 506        self.read(cx).has_deleted_file()
 507    }
 508
 509    pub fn has_conflict(&self, cx: &AppContext) -> bool {
 510        self.read(cx).has_conflict()
 511    }
 512
 513    // The `is_empty` signature doesn't match what clippy expects
 514    #[allow(clippy::len_without_is_empty)]
 515    pub fn len(&self, cx: &AppContext) -> usize {
 516        self.read(cx).len()
 517    }
 518
 519    pub fn is_empty(&self, cx: &AppContext) -> bool {
 520        self.len(cx) != 0
 521    }
 522
 523    pub fn symbols_containing<T: ToOffset>(
 524        &self,
 525        offset: T,
 526        theme: Option<&SyntaxTheme>,
 527        cx: &AppContext,
 528    ) -> Option<(BufferId, Vec<OutlineItem<Anchor>>)> {
 529        self.read(cx).symbols_containing(offset, theme)
 530    }
 531
 532    pub fn edit<I, S, T>(
 533        &self,
 534        edits: I,
 535        autoindent_mode: Option<AutoindentMode>,
 536        cx: &mut ModelContext<Self>,
 537    ) where
 538        I: IntoIterator<Item = (Range<S>, T)>,
 539        S: ToOffset,
 540        T: Into<Arc<str>>,
 541    {
 542        let snapshot = self.read(cx);
 543        let edits = edits
 544            .into_iter()
 545            .map(|(range, new_text)| {
 546                let mut range = range.start.to_offset(&snapshot)..range.end.to_offset(&snapshot);
 547                if range.start > range.end {
 548                    mem::swap(&mut range.start, &mut range.end);
 549                }
 550                (range, new_text.into())
 551            })
 552            .collect::<Vec<_>>();
 553
 554        return edit_internal(self, snapshot, edits, autoindent_mode, cx);
 555
 556        // Non-generic part of edit, hoisted out to avoid blowing up LLVM IR.
 557        fn edit_internal(
 558            this: &MultiBuffer,
 559            snapshot: Ref<MultiBufferSnapshot>,
 560            edits: Vec<(Range<usize>, Arc<str>)>,
 561            mut autoindent_mode: Option<AutoindentMode>,
 562            cx: &mut ModelContext<MultiBuffer>,
 563        ) {
 564            if this.read_only() || this.buffers.borrow().is_empty() {
 565                return;
 566            }
 567
 568            if let Some(buffer) = this.as_singleton() {
 569                buffer.update(cx, |buffer, cx| {
 570                    buffer.edit(edits, autoindent_mode, cx);
 571                });
 572                cx.emit(Event::ExcerptsEdited {
 573                    ids: this.excerpt_ids(),
 574                });
 575                return;
 576            }
 577
 578            let original_indent_columns = match &mut autoindent_mode {
 579                Some(AutoindentMode::Block {
 580                    original_indent_columns,
 581                }) => mem::take(original_indent_columns),
 582                _ => Default::default(),
 583            };
 584
 585            let (buffer_edits, edited_excerpt_ids) =
 586                this.convert_edits_to_buffer_edits(edits, &snapshot, &original_indent_columns);
 587            drop(snapshot);
 588
 589            for (buffer_id, mut edits) in buffer_edits {
 590                edits.sort_unstable_by_key(|edit| edit.range.start);
 591                this.buffers.borrow()[&buffer_id]
 592                    .buffer
 593                    .update(cx, |buffer, cx| {
 594                        let mut edits = edits.into_iter().peekable();
 595                        let mut insertions = Vec::new();
 596                        let mut original_indent_columns = Vec::new();
 597                        let mut deletions = Vec::new();
 598                        let empty_str: Arc<str> = Arc::default();
 599                        while let Some(BufferEdit {
 600                            mut range,
 601                            new_text,
 602                            mut is_insertion,
 603                            original_indent_column,
 604                        }) = edits.next()
 605                        {
 606                            while let Some(BufferEdit {
 607                                range: next_range,
 608                                is_insertion: next_is_insertion,
 609                                ..
 610                            }) = edits.peek()
 611                            {
 612                                if range.end >= next_range.start {
 613                                    range.end = cmp::max(next_range.end, range.end);
 614                                    is_insertion |= *next_is_insertion;
 615                                    edits.next();
 616                                } else {
 617                                    break;
 618                                }
 619                            }
 620
 621                            if is_insertion {
 622                                original_indent_columns.push(original_indent_column);
 623                                insertions.push((
 624                                    buffer.anchor_before(range.start)
 625                                        ..buffer.anchor_before(range.end),
 626                                    new_text.clone(),
 627                                ));
 628                            } else if !range.is_empty() {
 629                                deletions.push((
 630                                    buffer.anchor_before(range.start)
 631                                        ..buffer.anchor_before(range.end),
 632                                    empty_str.clone(),
 633                                ));
 634                            }
 635                        }
 636
 637                        let deletion_autoindent_mode =
 638                            if let Some(AutoindentMode::Block { .. }) = autoindent_mode {
 639                                Some(AutoindentMode::Block {
 640                                    original_indent_columns: Default::default(),
 641                                })
 642                            } else {
 643                                autoindent_mode.clone()
 644                            };
 645                        let insertion_autoindent_mode =
 646                            if let Some(AutoindentMode::Block { .. }) = autoindent_mode {
 647                                Some(AutoindentMode::Block {
 648                                    original_indent_columns,
 649                                })
 650                            } else {
 651                                autoindent_mode.clone()
 652                            };
 653
 654                        buffer.edit(deletions, deletion_autoindent_mode, cx);
 655                        buffer.edit(insertions, insertion_autoindent_mode, cx);
 656                    })
 657            }
 658
 659            cx.emit(Event::ExcerptsEdited {
 660                ids: edited_excerpt_ids,
 661            });
 662        }
 663    }
 664
 665    fn convert_edits_to_buffer_edits(
 666        &self,
 667        edits: Vec<(Range<usize>, Arc<str>)>,
 668        snapshot: &MultiBufferSnapshot,
 669        original_indent_columns: &[u32],
 670    ) -> (HashMap<BufferId, Vec<BufferEdit>>, Vec<ExcerptId>) {
 671        let mut buffer_edits: HashMap<BufferId, Vec<BufferEdit>> = Default::default();
 672        let mut edited_excerpt_ids = Vec::new();
 673        let mut cursor = snapshot.excerpts.cursor::<usize>(&());
 674        for (ix, (range, new_text)) in edits.into_iter().enumerate() {
 675            let original_indent_column = original_indent_columns.get(ix).copied().unwrap_or(0);
 676            cursor.seek(&range.start, Bias::Right, &());
 677            if cursor.item().is_none() && range.start == *cursor.start() {
 678                cursor.prev(&());
 679            }
 680            let start_excerpt = cursor.item().expect("start offset out of bounds");
 681            let start_overshoot = range.start - cursor.start();
 682            let buffer_start = start_excerpt
 683                .range
 684                .context
 685                .start
 686                .to_offset(&start_excerpt.buffer)
 687                + start_overshoot;
 688            edited_excerpt_ids.push(start_excerpt.id);
 689
 690            cursor.seek(&range.end, Bias::Right, &());
 691            if cursor.item().is_none() && range.end == *cursor.start() {
 692                cursor.prev(&());
 693            }
 694            let end_excerpt = cursor.item().expect("end offset out of bounds");
 695            let end_overshoot = range.end - cursor.start();
 696            let buffer_end = end_excerpt
 697                .range
 698                .context
 699                .start
 700                .to_offset(&end_excerpt.buffer)
 701                + end_overshoot;
 702
 703            if start_excerpt.id == end_excerpt.id {
 704                buffer_edits
 705                    .entry(start_excerpt.buffer_id)
 706                    .or_default()
 707                    .push(BufferEdit {
 708                        range: buffer_start..buffer_end,
 709                        new_text,
 710                        is_insertion: true,
 711                        original_indent_column,
 712                    });
 713            } else {
 714                edited_excerpt_ids.push(end_excerpt.id);
 715                let start_excerpt_range = buffer_start
 716                    ..start_excerpt
 717                        .range
 718                        .context
 719                        .end
 720                        .to_offset(&start_excerpt.buffer);
 721                let end_excerpt_range = end_excerpt
 722                    .range
 723                    .context
 724                    .start
 725                    .to_offset(&end_excerpt.buffer)
 726                    ..buffer_end;
 727                buffer_edits
 728                    .entry(start_excerpt.buffer_id)
 729                    .or_default()
 730                    .push(BufferEdit {
 731                        range: start_excerpt_range,
 732                        new_text: new_text.clone(),
 733                        is_insertion: true,
 734                        original_indent_column,
 735                    });
 736                buffer_edits
 737                    .entry(end_excerpt.buffer_id)
 738                    .or_default()
 739                    .push(BufferEdit {
 740                        range: end_excerpt_range,
 741                        new_text: new_text.clone(),
 742                        is_insertion: false,
 743                        original_indent_column,
 744                    });
 745
 746                cursor.seek(&range.start, Bias::Right, &());
 747                cursor.next(&());
 748                while let Some(excerpt) = cursor.item() {
 749                    if excerpt.id == end_excerpt.id {
 750                        break;
 751                    }
 752                    buffer_edits
 753                        .entry(excerpt.buffer_id)
 754                        .or_default()
 755                        .push(BufferEdit {
 756                            range: excerpt.range.context.to_offset(&excerpt.buffer),
 757                            new_text: new_text.clone(),
 758                            is_insertion: false,
 759                            original_indent_column,
 760                        });
 761                    edited_excerpt_ids.push(excerpt.id);
 762                    cursor.next(&());
 763                }
 764            }
 765        }
 766        (buffer_edits, edited_excerpt_ids)
 767    }
 768
 769    pub fn autoindent_ranges<I, S>(&self, ranges: I, cx: &mut ModelContext<Self>)
 770    where
 771        I: IntoIterator<Item = Range<S>>,
 772        S: ToOffset,
 773    {
 774        let snapshot = self.read(cx);
 775        let empty = Arc::<str>::from("");
 776        let edits = ranges
 777            .into_iter()
 778            .map(|range| {
 779                let mut range = range.start.to_offset(&snapshot)..range.end.to_offset(&snapshot);
 780                if range.start > range.end {
 781                    mem::swap(&mut range.start, &mut range.end);
 782                }
 783                (range, empty.clone())
 784            })
 785            .collect::<Vec<_>>();
 786
 787        return autoindent_ranges_internal(self, snapshot, edits, cx);
 788
 789        fn autoindent_ranges_internal(
 790            this: &MultiBuffer,
 791            snapshot: Ref<MultiBufferSnapshot>,
 792            edits: Vec<(Range<usize>, Arc<str>)>,
 793            cx: &mut ModelContext<MultiBuffer>,
 794        ) {
 795            if this.read_only() || this.buffers.borrow().is_empty() {
 796                return;
 797            }
 798
 799            if let Some(buffer) = this.as_singleton() {
 800                buffer.update(cx, |buffer, cx| {
 801                    buffer.autoindent_ranges(edits.into_iter().map(|e| e.0), cx);
 802                });
 803                cx.emit(Event::ExcerptsEdited {
 804                    ids: this.excerpt_ids(),
 805                });
 806                return;
 807            }
 808
 809            let (buffer_edits, edited_excerpt_ids) =
 810                this.convert_edits_to_buffer_edits(edits, &snapshot, &[]);
 811            drop(snapshot);
 812
 813            for (buffer_id, mut edits) in buffer_edits {
 814                edits.sort_unstable_by_key(|edit| edit.range.start);
 815
 816                let mut ranges: Vec<Range<usize>> = Vec::new();
 817                for edit in edits {
 818                    if let Some(last_range) = ranges.last_mut() {
 819                        if edit.range.start <= last_range.end {
 820                            last_range.end = last_range.end.max(edit.range.end);
 821                            continue;
 822                        }
 823                    }
 824                    ranges.push(edit.range);
 825                }
 826
 827                this.buffers.borrow()[&buffer_id]
 828                    .buffer
 829                    .update(cx, |buffer, cx| {
 830                        buffer.autoindent_ranges(ranges, cx);
 831                    })
 832            }
 833
 834            cx.emit(Event::ExcerptsEdited {
 835                ids: edited_excerpt_ids,
 836            });
 837        }
 838    }
 839
 840    // Inserts newlines at the given position to create an empty line, returning the start of the new line.
 841    // You can also request the insertion of empty lines above and below the line starting at the returned point.
 842    // Panics if the given position is invalid.
 843    pub fn insert_empty_line(
 844        &mut self,
 845        position: impl ToPoint,
 846        space_above: bool,
 847        space_below: bool,
 848        cx: &mut ModelContext<Self>,
 849    ) -> Point {
 850        let multibuffer_point = position.to_point(&self.read(cx));
 851        if let Some(buffer) = self.as_singleton() {
 852            buffer.update(cx, |buffer, cx| {
 853                buffer.insert_empty_line(multibuffer_point, space_above, space_below, cx)
 854            })
 855        } else {
 856            let (buffer, buffer_point, _) =
 857                self.point_to_buffer_point(multibuffer_point, cx).unwrap();
 858            self.start_transaction(cx);
 859            let empty_line_start = buffer.update(cx, |buffer, cx| {
 860                buffer.insert_empty_line(buffer_point, space_above, space_below, cx)
 861            });
 862            self.end_transaction(cx);
 863            multibuffer_point + (empty_line_start - buffer_point)
 864        }
 865    }
 866
 867    pub fn start_transaction(&mut self, cx: &mut ModelContext<Self>) -> Option<TransactionId> {
 868        self.start_transaction_at(Instant::now(), cx)
 869    }
 870
 871    pub fn start_transaction_at(
 872        &mut self,
 873        now: Instant,
 874        cx: &mut ModelContext<Self>,
 875    ) -> Option<TransactionId> {
 876        if let Some(buffer) = self.as_singleton() {
 877            return buffer.update(cx, |buffer, _| buffer.start_transaction_at(now));
 878        }
 879
 880        for BufferState { buffer, .. } in self.buffers.borrow().values() {
 881            buffer.update(cx, |buffer, _| buffer.start_transaction_at(now));
 882        }
 883        self.history.start_transaction(now)
 884    }
 885
 886    pub fn end_transaction(&mut self, cx: &mut ModelContext<Self>) -> Option<TransactionId> {
 887        self.end_transaction_at(Instant::now(), cx)
 888    }
 889
 890    pub fn end_transaction_at(
 891        &mut self,
 892        now: Instant,
 893        cx: &mut ModelContext<Self>,
 894    ) -> Option<TransactionId> {
 895        if let Some(buffer) = self.as_singleton() {
 896            return buffer.update(cx, |buffer, cx| buffer.end_transaction_at(now, cx));
 897        }
 898
 899        let mut buffer_transactions = HashMap::default();
 900        for BufferState { buffer, .. } in self.buffers.borrow().values() {
 901            if let Some(transaction_id) =
 902                buffer.update(cx, |buffer, cx| buffer.end_transaction_at(now, cx))
 903            {
 904                buffer_transactions.insert(buffer.read(cx).remote_id(), transaction_id);
 905            }
 906        }
 907
 908        if self.history.end_transaction(now, buffer_transactions) {
 909            let transaction_id = self.history.group().unwrap();
 910            Some(transaction_id)
 911        } else {
 912            None
 913        }
 914    }
 915
 916    pub fn edited_ranges_for_transaction<D>(
 917        &self,
 918        transaction_id: TransactionId,
 919        cx: &AppContext,
 920    ) -> Vec<Range<D>>
 921    where
 922        D: TextDimension + Ord + Sub<D, Output = D>,
 923    {
 924        if let Some(buffer) = self.as_singleton() {
 925            return buffer
 926                .read(cx)
 927                .edited_ranges_for_transaction_id(transaction_id)
 928                .collect::<Vec<_>>();
 929        }
 930
 931        let Some(transaction) = self.history.transaction(transaction_id) else {
 932            return Vec::new();
 933        };
 934
 935        let mut ranges = Vec::new();
 936        let snapshot = self.read(cx);
 937        let buffers = self.buffers.borrow();
 938        let mut cursor = snapshot.excerpts.cursor::<ExcerptSummary>(&());
 939
 940        for (buffer_id, buffer_transaction) in &transaction.buffer_transactions {
 941            let Some(buffer_state) = buffers.get(buffer_id) else {
 942                continue;
 943            };
 944
 945            let buffer = buffer_state.buffer.read(cx);
 946            for range in buffer.edited_ranges_for_transaction_id::<D>(*buffer_transaction) {
 947                for excerpt_id in &buffer_state.excerpts {
 948                    cursor.seek(excerpt_id, Bias::Left, &());
 949                    if let Some(excerpt) = cursor.item() {
 950                        if excerpt.locator == *excerpt_id {
 951                            let excerpt_buffer_start =
 952                                excerpt.range.context.start.summary::<D>(buffer);
 953                            let excerpt_buffer_end = excerpt.range.context.end.summary::<D>(buffer);
 954                            let excerpt_range = excerpt_buffer_start.clone()..excerpt_buffer_end;
 955                            if excerpt_range.contains(&range.start)
 956                                && excerpt_range.contains(&range.end)
 957                            {
 958                                let excerpt_start = D::from_text_summary(&cursor.start().text);
 959
 960                                let mut start = excerpt_start.clone();
 961                                start.add_assign(&(range.start - excerpt_buffer_start.clone()));
 962                                let mut end = excerpt_start;
 963                                end.add_assign(&(range.end - excerpt_buffer_start));
 964
 965                                ranges.push(start..end);
 966                                break;
 967                            }
 968                        }
 969                    }
 970                }
 971            }
 972        }
 973
 974        ranges.sort_by_key(|range| range.start.clone());
 975        ranges
 976    }
 977
 978    pub fn merge_transactions(
 979        &mut self,
 980        transaction: TransactionId,
 981        destination: TransactionId,
 982        cx: &mut ModelContext<Self>,
 983    ) {
 984        if let Some(buffer) = self.as_singleton() {
 985            buffer.update(cx, |buffer, _| {
 986                buffer.merge_transactions(transaction, destination)
 987            });
 988        } else if let Some(transaction) = self.history.forget(transaction) {
 989            if let Some(destination) = self.history.transaction_mut(destination) {
 990                for (buffer_id, buffer_transaction_id) in transaction.buffer_transactions {
 991                    if let Some(destination_buffer_transaction_id) =
 992                        destination.buffer_transactions.get(&buffer_id)
 993                    {
 994                        if let Some(state) = self.buffers.borrow().get(&buffer_id) {
 995                            state.buffer.update(cx, |buffer, _| {
 996                                buffer.merge_transactions(
 997                                    buffer_transaction_id,
 998                                    *destination_buffer_transaction_id,
 999                                )
1000                            });
1001                        }
1002                    } else {
1003                        destination
1004                            .buffer_transactions
1005                            .insert(buffer_id, buffer_transaction_id);
1006                    }
1007                }
1008            }
1009        }
1010    }
1011
1012    pub fn finalize_last_transaction(&mut self, cx: &mut ModelContext<Self>) {
1013        self.history.finalize_last_transaction();
1014        for BufferState { buffer, .. } in self.buffers.borrow().values() {
1015            buffer.update(cx, |buffer, _| {
1016                buffer.finalize_last_transaction();
1017            });
1018        }
1019    }
1020
1021    pub fn push_transaction<'a, T>(&mut self, buffer_transactions: T, cx: &ModelContext<Self>)
1022    where
1023        T: IntoIterator<Item = (&'a Model<Buffer>, &'a language::Transaction)>,
1024    {
1025        self.history
1026            .push_transaction(buffer_transactions, Instant::now(), cx);
1027        self.history.finalize_last_transaction();
1028    }
1029
1030    pub fn group_until_transaction(
1031        &mut self,
1032        transaction_id: TransactionId,
1033        cx: &mut ModelContext<Self>,
1034    ) {
1035        if let Some(buffer) = self.as_singleton() {
1036            buffer.update(cx, |buffer, _| {
1037                buffer.group_until_transaction(transaction_id)
1038            });
1039        } else {
1040            self.history.group_until(transaction_id);
1041        }
1042    }
1043
1044    pub fn set_active_selections(
1045        &self,
1046        selections: &[Selection<Anchor>],
1047        line_mode: bool,
1048        cursor_shape: CursorShape,
1049        cx: &mut ModelContext<Self>,
1050    ) {
1051        let mut selections_by_buffer: HashMap<BufferId, Vec<Selection<text::Anchor>>> =
1052            Default::default();
1053        let snapshot = self.read(cx);
1054        let mut cursor = snapshot.excerpts.cursor::<Option<&Locator>>(&());
1055        for selection in selections {
1056            let start_locator = snapshot.excerpt_locator_for_id(selection.start.excerpt_id);
1057            let end_locator = snapshot.excerpt_locator_for_id(selection.end.excerpt_id);
1058
1059            cursor.seek(&Some(start_locator), Bias::Left, &());
1060            while let Some(excerpt) = cursor.item() {
1061                if excerpt.locator > *end_locator {
1062                    break;
1063                }
1064
1065                let mut start = excerpt.range.context.start;
1066                let mut end = excerpt.range.context.end;
1067                if excerpt.id == selection.start.excerpt_id {
1068                    start = selection.start.text_anchor;
1069                }
1070                if excerpt.id == selection.end.excerpt_id {
1071                    end = selection.end.text_anchor;
1072                }
1073                selections_by_buffer
1074                    .entry(excerpt.buffer_id)
1075                    .or_default()
1076                    .push(Selection {
1077                        id: selection.id,
1078                        start,
1079                        end,
1080                        reversed: selection.reversed,
1081                        goal: selection.goal,
1082                    });
1083
1084                cursor.next(&());
1085            }
1086        }
1087
1088        for (buffer_id, buffer_state) in self.buffers.borrow().iter() {
1089            if !selections_by_buffer.contains_key(buffer_id) {
1090                buffer_state
1091                    .buffer
1092                    .update(cx, |buffer, cx| buffer.remove_active_selections(cx));
1093            }
1094        }
1095
1096        for (buffer_id, mut selections) in selections_by_buffer {
1097            self.buffers.borrow()[&buffer_id]
1098                .buffer
1099                .update(cx, |buffer, cx| {
1100                    selections.sort_unstable_by(|a, b| a.start.cmp(&b.start, buffer));
1101                    let mut selections = selections.into_iter().peekable();
1102                    let merged_selections = Arc::from_iter(iter::from_fn(|| {
1103                        let mut selection = selections.next()?;
1104                        while let Some(next_selection) = selections.peek() {
1105                            if selection.end.cmp(&next_selection.start, buffer).is_ge() {
1106                                let next_selection = selections.next().unwrap();
1107                                if next_selection.end.cmp(&selection.end, buffer).is_ge() {
1108                                    selection.end = next_selection.end;
1109                                }
1110                            } else {
1111                                break;
1112                            }
1113                        }
1114                        Some(selection)
1115                    }));
1116                    buffer.set_active_selections(merged_selections, line_mode, cursor_shape, cx);
1117                });
1118        }
1119    }
1120
1121    pub fn remove_active_selections(&self, cx: &mut ModelContext<Self>) {
1122        for buffer in self.buffers.borrow().values() {
1123            buffer
1124                .buffer
1125                .update(cx, |buffer, cx| buffer.remove_active_selections(cx));
1126        }
1127    }
1128
1129    pub fn undo(&mut self, cx: &mut ModelContext<Self>) -> Option<TransactionId> {
1130        let mut transaction_id = None;
1131        if let Some(buffer) = self.as_singleton() {
1132            transaction_id = buffer.update(cx, |buffer, cx| buffer.undo(cx));
1133        } else {
1134            while let Some(transaction) = self.history.pop_undo() {
1135                let mut undone = false;
1136                for (buffer_id, buffer_transaction_id) in &mut transaction.buffer_transactions {
1137                    if let Some(BufferState { buffer, .. }) = self.buffers.borrow().get(buffer_id) {
1138                        undone |= buffer.update(cx, |buffer, cx| {
1139                            let undo_to = *buffer_transaction_id;
1140                            if let Some(entry) = buffer.peek_undo_stack() {
1141                                *buffer_transaction_id = entry.transaction_id();
1142                            }
1143                            buffer.undo_to_transaction(undo_to, cx)
1144                        });
1145                    }
1146                }
1147
1148                if undone {
1149                    transaction_id = Some(transaction.id);
1150                    break;
1151                }
1152            }
1153        }
1154
1155        if let Some(transaction_id) = transaction_id {
1156            cx.emit(Event::TransactionUndone { transaction_id });
1157        }
1158
1159        transaction_id
1160    }
1161
1162    pub fn redo(&mut self, cx: &mut ModelContext<Self>) -> Option<TransactionId> {
1163        if let Some(buffer) = self.as_singleton() {
1164            return buffer.update(cx, |buffer, cx| buffer.redo(cx));
1165        }
1166
1167        while let Some(transaction) = self.history.pop_redo() {
1168            let mut redone = false;
1169            for (buffer_id, buffer_transaction_id) in &mut transaction.buffer_transactions {
1170                if let Some(BufferState { buffer, .. }) = self.buffers.borrow().get(buffer_id) {
1171                    redone |= buffer.update(cx, |buffer, cx| {
1172                        let redo_to = *buffer_transaction_id;
1173                        if let Some(entry) = buffer.peek_redo_stack() {
1174                            *buffer_transaction_id = entry.transaction_id();
1175                        }
1176                        buffer.redo_to_transaction(redo_to, cx)
1177                    });
1178                }
1179            }
1180
1181            if redone {
1182                return Some(transaction.id);
1183            }
1184        }
1185
1186        None
1187    }
1188
1189    pub fn undo_transaction(&mut self, transaction_id: TransactionId, cx: &mut ModelContext<Self>) {
1190        if let Some(buffer) = self.as_singleton() {
1191            buffer.update(cx, |buffer, cx| buffer.undo_transaction(transaction_id, cx));
1192        } else if let Some(transaction) = self.history.remove_from_undo(transaction_id) {
1193            for (buffer_id, transaction_id) in &transaction.buffer_transactions {
1194                if let Some(BufferState { buffer, .. }) = self.buffers.borrow().get(buffer_id) {
1195                    buffer.update(cx, |buffer, cx| {
1196                        buffer.undo_transaction(*transaction_id, cx)
1197                    });
1198                }
1199            }
1200        }
1201    }
1202
1203    pub fn forget_transaction(
1204        &mut self,
1205        transaction_id: TransactionId,
1206        cx: &mut ModelContext<Self>,
1207    ) {
1208        if let Some(buffer) = self.as_singleton() {
1209            buffer.update(cx, |buffer, _| {
1210                buffer.forget_transaction(transaction_id);
1211            });
1212        } else if let Some(transaction) = self.history.forget(transaction_id) {
1213            for (buffer_id, buffer_transaction_id) in transaction.buffer_transactions {
1214                if let Some(state) = self.buffers.borrow_mut().get_mut(&buffer_id) {
1215                    state.buffer.update(cx, |buffer, _| {
1216                        buffer.forget_transaction(buffer_transaction_id);
1217                    });
1218                }
1219            }
1220        }
1221    }
1222
1223    pub fn push_excerpts<O>(
1224        &mut self,
1225        buffer: Model<Buffer>,
1226        ranges: impl IntoIterator<Item = ExcerptRange<O>>,
1227        cx: &mut ModelContext<Self>,
1228    ) -> Vec<ExcerptId>
1229    where
1230        O: text::ToOffset,
1231    {
1232        self.insert_excerpts_after(ExcerptId::max(), buffer, ranges, cx)
1233    }
1234
1235    pub fn push_excerpts_with_context_lines<O>(
1236        &mut self,
1237        buffer: Model<Buffer>,
1238        ranges: Vec<Range<O>>,
1239        context_line_count: u32,
1240        cx: &mut ModelContext<Self>,
1241    ) -> Vec<Range<Anchor>>
1242    where
1243        O: text::ToPoint + text::ToOffset,
1244    {
1245        let buffer_id = buffer.read(cx).remote_id();
1246        let buffer_snapshot = buffer.read(cx).snapshot();
1247        let (excerpt_ranges, range_counts) =
1248            build_excerpt_ranges(&buffer_snapshot, &ranges, context_line_count);
1249
1250        let excerpt_ids = self.push_excerpts(buffer, excerpt_ranges, cx);
1251
1252        let mut anchor_ranges = Vec::new();
1253        let mut ranges = ranges.into_iter();
1254        for (excerpt_id, range_count) in excerpt_ids.into_iter().zip(range_counts.into_iter()) {
1255            anchor_ranges.extend(ranges.by_ref().take(range_count).map(|range| {
1256                let start = Anchor {
1257                    buffer_id: Some(buffer_id),
1258                    excerpt_id,
1259                    text_anchor: buffer_snapshot.anchor_after(range.start),
1260                };
1261                let end = Anchor {
1262                    buffer_id: Some(buffer_id),
1263                    excerpt_id,
1264                    text_anchor: buffer_snapshot.anchor_after(range.end),
1265                };
1266                start..end
1267            }))
1268        }
1269        anchor_ranges
1270    }
1271
1272    pub fn push_multiple_excerpts_with_context_lines(
1273        &self,
1274        buffers_with_ranges: Vec<(Model<Buffer>, Vec<Range<text::Anchor>>)>,
1275        context_line_count: u32,
1276        cx: &mut ModelContext<Self>,
1277    ) -> Task<Vec<Range<Anchor>>> {
1278        use futures::StreamExt;
1279
1280        let (excerpt_ranges_tx, mut excerpt_ranges_rx) = mpsc::channel(256);
1281
1282        let mut buffer_ids = Vec::with_capacity(buffers_with_ranges.len());
1283
1284        for (buffer, ranges) in buffers_with_ranges {
1285            let (buffer_id, buffer_snapshot) =
1286                buffer.update(cx, |buffer, _| (buffer.remote_id(), buffer.snapshot()));
1287
1288            buffer_ids.push(buffer_id);
1289
1290            cx.background_executor()
1291                .spawn({
1292                    let mut excerpt_ranges_tx = excerpt_ranges_tx.clone();
1293
1294                    async move {
1295                        let (excerpt_ranges, counts) =
1296                            build_excerpt_ranges(&buffer_snapshot, &ranges, context_line_count);
1297                        excerpt_ranges_tx
1298                            .send((buffer_id, buffer.clone(), ranges, excerpt_ranges, counts))
1299                            .await
1300                            .ok();
1301                    }
1302                })
1303                .detach()
1304        }
1305
1306        cx.spawn(move |this, mut cx| async move {
1307            let mut results_by_buffer_id = HashMap::default();
1308            while let Some((buffer_id, buffer, ranges, excerpt_ranges, range_counts)) =
1309                excerpt_ranges_rx.next().await
1310            {
1311                results_by_buffer_id
1312                    .insert(buffer_id, (buffer, ranges, excerpt_ranges, range_counts));
1313            }
1314
1315            let mut multi_buffer_ranges = Vec::default();
1316            'outer: for buffer_id in buffer_ids {
1317                let Some((buffer, ranges, excerpt_ranges, range_counts)) =
1318                    results_by_buffer_id.remove(&buffer_id)
1319                else {
1320                    continue;
1321                };
1322
1323                let mut ranges = ranges.into_iter();
1324                let mut range_counts = range_counts.into_iter();
1325                for excerpt_ranges in excerpt_ranges.chunks(100) {
1326                    let excerpt_ids = match this.update(&mut cx, |this, cx| {
1327                        this.push_excerpts(buffer.clone(), excerpt_ranges.iter().cloned(), cx)
1328                    }) {
1329                        Ok(excerpt_ids) => excerpt_ids,
1330                        Err(_) => continue 'outer,
1331                    };
1332
1333                    for (excerpt_id, range_count) in
1334                        excerpt_ids.into_iter().zip(range_counts.by_ref())
1335                    {
1336                        for range in ranges.by_ref().take(range_count) {
1337                            let start = Anchor {
1338                                buffer_id: Some(buffer_id),
1339                                excerpt_id,
1340                                text_anchor: range.start,
1341                            };
1342                            let end = Anchor {
1343                                buffer_id: Some(buffer_id),
1344                                excerpt_id,
1345                                text_anchor: range.end,
1346                            };
1347                            multi_buffer_ranges.push(start..end);
1348                        }
1349                    }
1350                }
1351            }
1352
1353            multi_buffer_ranges
1354        })
1355    }
1356
1357    pub fn insert_excerpts_after<O>(
1358        &mut self,
1359        prev_excerpt_id: ExcerptId,
1360        buffer: Model<Buffer>,
1361        ranges: impl IntoIterator<Item = ExcerptRange<O>>,
1362        cx: &mut ModelContext<Self>,
1363    ) -> Vec<ExcerptId>
1364    where
1365        O: text::ToOffset,
1366    {
1367        let mut ids = Vec::new();
1368        let mut next_excerpt_id =
1369            if let Some(last_entry) = self.snapshot.borrow().excerpt_ids.last() {
1370                last_entry.id.0 + 1
1371            } else {
1372                1
1373            };
1374        self.insert_excerpts_with_ids_after(
1375            prev_excerpt_id,
1376            buffer,
1377            ranges.into_iter().map(|range| {
1378                let id = ExcerptId(post_inc(&mut next_excerpt_id));
1379                ids.push(id);
1380                (id, range)
1381            }),
1382            cx,
1383        );
1384        ids
1385    }
1386
1387    pub fn insert_excerpts_with_ids_after<O>(
1388        &mut self,
1389        prev_excerpt_id: ExcerptId,
1390        buffer: Model<Buffer>,
1391        ranges: impl IntoIterator<Item = (ExcerptId, ExcerptRange<O>)>,
1392        cx: &mut ModelContext<Self>,
1393    ) where
1394        O: text::ToOffset,
1395    {
1396        assert_eq!(self.history.transaction_depth, 0);
1397        let mut ranges = ranges.into_iter().peekable();
1398        if ranges.peek().is_none() {
1399            return Default::default();
1400        }
1401
1402        self.sync(cx);
1403
1404        let buffer_id = buffer.read(cx).remote_id();
1405        let buffer_snapshot = buffer.read(cx).snapshot();
1406
1407        let mut buffers = self.buffers.borrow_mut();
1408        let buffer_state = buffers.entry(buffer_id).or_insert_with(|| BufferState {
1409            last_version: buffer_snapshot.version().clone(),
1410            last_non_text_state_update_count: buffer_snapshot.non_text_state_update_count(),
1411            excerpts: Default::default(),
1412            _subscriptions: [
1413                cx.observe(&buffer, |_, _, cx| cx.notify()),
1414                cx.subscribe(&buffer, Self::on_buffer_event),
1415            ],
1416            buffer: buffer.clone(),
1417        });
1418
1419        let mut snapshot = self.snapshot.borrow_mut();
1420
1421        let mut prev_locator = snapshot.excerpt_locator_for_id(prev_excerpt_id).clone();
1422        let mut new_excerpt_ids = mem::take(&mut snapshot.excerpt_ids);
1423        let mut cursor = snapshot.excerpts.cursor::<Option<&Locator>>(&());
1424        let mut new_excerpts = cursor.slice(&prev_locator, Bias::Right, &());
1425        prev_locator = cursor.start().unwrap_or(Locator::min_ref()).clone();
1426
1427        let edit_start = new_excerpts.summary().text.len;
1428        new_excerpts.update_last(
1429            |excerpt| {
1430                excerpt.has_trailing_newline = true;
1431            },
1432            &(),
1433        );
1434
1435        let next_locator = if let Some(excerpt) = cursor.item() {
1436            excerpt.locator.clone()
1437        } else {
1438            Locator::max()
1439        };
1440
1441        let mut excerpts = Vec::new();
1442        while let Some((id, range)) = ranges.next() {
1443            let locator = Locator::between(&prev_locator, &next_locator);
1444            if let Err(ix) = buffer_state.excerpts.binary_search(&locator) {
1445                buffer_state.excerpts.insert(ix, locator.clone());
1446            }
1447            let range = ExcerptRange {
1448                context: buffer_snapshot.anchor_before(&range.context.start)
1449                    ..buffer_snapshot.anchor_after(&range.context.end),
1450                primary: range.primary.map(|primary| {
1451                    buffer_snapshot.anchor_before(&primary.start)
1452                        ..buffer_snapshot.anchor_after(&primary.end)
1453                }),
1454            };
1455            excerpts.push((id, range.clone()));
1456            let excerpt = Excerpt::new(
1457                id,
1458                locator.clone(),
1459                buffer_id,
1460                buffer_snapshot.clone(),
1461                range,
1462                ranges.peek().is_some() || cursor.item().is_some(),
1463            );
1464            new_excerpts.push(excerpt, &());
1465            prev_locator = locator.clone();
1466
1467            if let Some(last_mapping_entry) = new_excerpt_ids.last() {
1468                assert!(id > last_mapping_entry.id, "excerpt ids must be increasing");
1469            }
1470            new_excerpt_ids.push(ExcerptIdMapping { id, locator }, &());
1471        }
1472
1473        let edit_end = new_excerpts.summary().text.len;
1474
1475        let suffix = cursor.suffix(&());
1476        let changed_trailing_excerpt = suffix.is_empty();
1477        new_excerpts.append(suffix, &());
1478        drop(cursor);
1479        snapshot.excerpts = new_excerpts;
1480        snapshot.excerpt_ids = new_excerpt_ids;
1481        if changed_trailing_excerpt {
1482            snapshot.trailing_excerpt_update_count += 1;
1483        }
1484
1485        self.subscriptions.publish_mut([Edit {
1486            old: edit_start..edit_start,
1487            new: edit_start..edit_end,
1488        }]);
1489        cx.emit(Event::Edited {
1490            singleton_buffer_edited: false,
1491        });
1492        cx.emit(Event::ExcerptsAdded {
1493            buffer,
1494            predecessor: prev_excerpt_id,
1495            excerpts,
1496        });
1497        cx.notify();
1498    }
1499
1500    pub fn clear(&mut self, cx: &mut ModelContext<Self>) {
1501        self.sync(cx);
1502        let ids = self.excerpt_ids();
1503        self.buffers.borrow_mut().clear();
1504        let mut snapshot = self.snapshot.borrow_mut();
1505        let prev_len = snapshot.len();
1506        snapshot.excerpts = Default::default();
1507        snapshot.trailing_excerpt_update_count += 1;
1508        snapshot.is_dirty = false;
1509        snapshot.has_deleted_file = false;
1510        snapshot.has_conflict = false;
1511
1512        self.subscriptions.publish_mut([Edit {
1513            old: 0..prev_len,
1514            new: 0..0,
1515        }]);
1516        cx.emit(Event::Edited {
1517            singleton_buffer_edited: false,
1518        });
1519        cx.emit(Event::ExcerptsRemoved { ids });
1520        cx.notify();
1521    }
1522
1523    pub fn excerpts_for_buffer(
1524        &self,
1525        buffer: &Model<Buffer>,
1526        cx: &AppContext,
1527    ) -> Vec<(ExcerptId, ExcerptRange<text::Anchor>)> {
1528        let mut excerpts = Vec::new();
1529        let snapshot = self.read(cx);
1530        let buffers = self.buffers.borrow();
1531        let mut cursor = snapshot.excerpts.cursor::<Option<&Locator>>(&());
1532        for locator in buffers
1533            .get(&buffer.read(cx).remote_id())
1534            .map(|state| &state.excerpts)
1535            .into_iter()
1536            .flatten()
1537        {
1538            cursor.seek_forward(&Some(locator), Bias::Left, &());
1539            if let Some(excerpt) = cursor.item() {
1540                if excerpt.locator == *locator {
1541                    excerpts.push((excerpt.id, excerpt.range.clone()));
1542                }
1543            }
1544        }
1545
1546        excerpts
1547    }
1548
1549    pub fn excerpt_buffer_ids(&self) -> Vec<BufferId> {
1550        self.snapshot
1551            .borrow()
1552            .excerpts
1553            .iter()
1554            .map(|entry| entry.buffer_id)
1555            .collect()
1556    }
1557
1558    pub fn excerpt_ids(&self) -> Vec<ExcerptId> {
1559        self.snapshot
1560            .borrow()
1561            .excerpts
1562            .iter()
1563            .map(|entry| entry.id)
1564            .collect()
1565    }
1566
1567    pub fn excerpt_containing(
1568        &self,
1569        position: impl ToOffset,
1570        cx: &AppContext,
1571    ) -> Option<(ExcerptId, Model<Buffer>, Range<text::Anchor>)> {
1572        let snapshot = self.read(cx);
1573        let position = position.to_offset(&snapshot);
1574
1575        let mut cursor = snapshot.excerpts.cursor::<usize>(&());
1576        cursor.seek(&position, Bias::Right, &());
1577        cursor
1578            .item()
1579            .or_else(|| snapshot.excerpts.last())
1580            .map(|excerpt| {
1581                (
1582                    excerpt.id,
1583                    self.buffers
1584                        .borrow()
1585                        .get(&excerpt.buffer_id)
1586                        .unwrap()
1587                        .buffer
1588                        .clone(),
1589                    excerpt.range.context.clone(),
1590                )
1591            })
1592    }
1593
1594    // If point is at the end of the buffer, the last excerpt is returned
1595    pub fn point_to_buffer_offset<T: ToOffset>(
1596        &self,
1597        point: T,
1598        cx: &AppContext,
1599    ) -> Option<(Model<Buffer>, usize, ExcerptId)> {
1600        let snapshot = self.read(cx);
1601        let offset = point.to_offset(&snapshot);
1602        let mut cursor = snapshot.excerpts.cursor::<usize>(&());
1603        cursor.seek(&offset, Bias::Right, &());
1604        if cursor.item().is_none() {
1605            cursor.prev(&());
1606        }
1607
1608        cursor.item().map(|excerpt| {
1609            let excerpt_start = excerpt.range.context.start.to_offset(&excerpt.buffer);
1610            let buffer_point = excerpt_start + offset - *cursor.start();
1611            let buffer = self.buffers.borrow()[&excerpt.buffer_id].buffer.clone();
1612
1613            (buffer, buffer_point, excerpt.id)
1614        })
1615    }
1616
1617    // If point is at the end of the buffer, the last excerpt is returned
1618    pub fn point_to_buffer_point<T: ToPoint>(
1619        &self,
1620        point: T,
1621        cx: &AppContext,
1622    ) -> Option<(Model<Buffer>, Point, ExcerptId)> {
1623        let snapshot = self.read(cx);
1624        let point = point.to_point(&snapshot);
1625        let mut cursor = snapshot.excerpts.cursor::<Point>(&());
1626        cursor.seek(&point, Bias::Right, &());
1627        if cursor.item().is_none() {
1628            cursor.prev(&());
1629        }
1630
1631        cursor.item().map(|excerpt| {
1632            let excerpt_start = excerpt.range.context.start.to_point(&excerpt.buffer);
1633            let buffer_point = excerpt_start + point - *cursor.start();
1634            let buffer = self.buffers.borrow()[&excerpt.buffer_id].buffer.clone();
1635
1636            (buffer, buffer_point, excerpt.id)
1637        })
1638    }
1639
1640    pub fn range_to_buffer_ranges<T: ToOffset>(
1641        &self,
1642        range: Range<T>,
1643        cx: &AppContext,
1644    ) -> Vec<(Model<Buffer>, Range<usize>, ExcerptId)> {
1645        let snapshot = self.read(cx);
1646        let start = range.start.to_offset(&snapshot);
1647        let end = range.end.to_offset(&snapshot);
1648
1649        let mut result = Vec::new();
1650        let mut cursor = snapshot.excerpts.cursor::<usize>(&());
1651        cursor.seek(&start, Bias::Right, &());
1652        if cursor.item().is_none() {
1653            cursor.prev(&());
1654        }
1655
1656        while let Some(excerpt) = cursor.item() {
1657            if *cursor.start() > end {
1658                break;
1659            }
1660
1661            let mut end_before_newline = cursor.end(&());
1662            if excerpt.has_trailing_newline {
1663                end_before_newline -= 1;
1664            }
1665            let excerpt_start = excerpt.range.context.start.to_offset(&excerpt.buffer);
1666            let start = excerpt_start + (cmp::max(start, *cursor.start()) - *cursor.start());
1667            let end = excerpt_start + (cmp::min(end, end_before_newline) - *cursor.start());
1668            let buffer = self.buffers.borrow()[&excerpt.buffer_id].buffer.clone();
1669            result.push((buffer, start..end, excerpt.id));
1670            cursor.next(&());
1671        }
1672
1673        result
1674    }
1675
1676    pub fn remove_excerpts(
1677        &mut self,
1678        excerpt_ids: impl IntoIterator<Item = ExcerptId>,
1679        cx: &mut ModelContext<Self>,
1680    ) {
1681        self.sync(cx);
1682        let ids = excerpt_ids.into_iter().collect::<Vec<_>>();
1683        if ids.is_empty() {
1684            return;
1685        }
1686
1687        let mut buffers = self.buffers.borrow_mut();
1688        let mut snapshot = self.snapshot.borrow_mut();
1689        let mut new_excerpts = SumTree::default();
1690        let mut cursor = snapshot.excerpts.cursor::<(Option<&Locator>, usize)>(&());
1691        let mut edits = Vec::new();
1692        let mut excerpt_ids = ids.iter().copied().peekable();
1693
1694        while let Some(excerpt_id) = excerpt_ids.next() {
1695            // Seek to the next excerpt to remove, preserving any preceding excerpts.
1696            let locator = snapshot.excerpt_locator_for_id(excerpt_id);
1697            new_excerpts.append(cursor.slice(&Some(locator), Bias::Left, &()), &());
1698
1699            if let Some(mut excerpt) = cursor.item() {
1700                if excerpt.id != excerpt_id {
1701                    continue;
1702                }
1703                let mut old_start = cursor.start().1;
1704
1705                // Skip over the removed excerpt.
1706                'remove_excerpts: loop {
1707                    if let Some(buffer_state) = buffers.get_mut(&excerpt.buffer_id) {
1708                        buffer_state.excerpts.retain(|l| l != &excerpt.locator);
1709                        if buffer_state.excerpts.is_empty() {
1710                            buffers.remove(&excerpt.buffer_id);
1711                        }
1712                    }
1713                    cursor.next(&());
1714
1715                    // Skip over any subsequent excerpts that are also removed.
1716                    if let Some(&next_excerpt_id) = excerpt_ids.peek() {
1717                        let next_locator = snapshot.excerpt_locator_for_id(next_excerpt_id);
1718                        if let Some(next_excerpt) = cursor.item() {
1719                            if next_excerpt.locator == *next_locator {
1720                                excerpt_ids.next();
1721                                excerpt = next_excerpt;
1722                                continue 'remove_excerpts;
1723                            }
1724                        }
1725                    }
1726
1727                    break;
1728                }
1729
1730                // When removing the last excerpt, remove the trailing newline from
1731                // the previous excerpt.
1732                if cursor.item().is_none() && old_start > 0 {
1733                    old_start -= 1;
1734                    new_excerpts.update_last(|e| e.has_trailing_newline = false, &());
1735                }
1736
1737                // Push an edit for the removal of this run of excerpts.
1738                let old_end = cursor.start().1;
1739                let new_start = new_excerpts.summary().text.len;
1740                edits.push(Edit {
1741                    old: old_start..old_end,
1742                    new: new_start..new_start,
1743                });
1744            }
1745        }
1746        let suffix = cursor.suffix(&());
1747        let changed_trailing_excerpt = suffix.is_empty();
1748        new_excerpts.append(suffix, &());
1749        drop(cursor);
1750        snapshot.excerpts = new_excerpts;
1751
1752        if changed_trailing_excerpt {
1753            snapshot.trailing_excerpt_update_count += 1;
1754        }
1755
1756        self.subscriptions.publish_mut(edits);
1757        cx.emit(Event::Edited {
1758            singleton_buffer_edited: false,
1759        });
1760        cx.emit(Event::ExcerptsRemoved { ids });
1761        cx.notify();
1762    }
1763
1764    pub fn wait_for_anchors<'a>(
1765        &self,
1766        anchors: impl 'a + Iterator<Item = Anchor>,
1767        cx: &mut ModelContext<Self>,
1768    ) -> impl 'static + Future<Output = Result<()>> {
1769        let borrow = self.buffers.borrow();
1770        let mut error = None;
1771        let mut futures = Vec::new();
1772        for anchor in anchors {
1773            if let Some(buffer_id) = anchor.buffer_id {
1774                if let Some(buffer) = borrow.get(&buffer_id) {
1775                    buffer.buffer.update(cx, |buffer, _| {
1776                        futures.push(buffer.wait_for_anchors([anchor.text_anchor]))
1777                    });
1778                } else {
1779                    error = Some(anyhow!(
1780                        "buffer {buffer_id} is not part of this multi-buffer"
1781                    ));
1782                    break;
1783                }
1784            }
1785        }
1786        async move {
1787            if let Some(error) = error {
1788                Err(error)?;
1789            }
1790            for future in futures {
1791                future.await?;
1792            }
1793            Ok(())
1794        }
1795    }
1796
1797    pub fn text_anchor_for_position<T: ToOffset>(
1798        &self,
1799        position: T,
1800        cx: &AppContext,
1801    ) -> Option<(Model<Buffer>, language::Anchor)> {
1802        let snapshot = self.read(cx);
1803        let anchor = snapshot.anchor_before(position);
1804        let buffer = self
1805            .buffers
1806            .borrow()
1807            .get(&anchor.buffer_id?)?
1808            .buffer
1809            .clone();
1810        Some((buffer, anchor.text_anchor))
1811    }
1812
1813    fn on_buffer_event(
1814        &mut self,
1815        buffer: Model<Buffer>,
1816        event: &language::BufferEvent,
1817        cx: &mut ModelContext<Self>,
1818    ) {
1819        cx.emit(match event {
1820            language::BufferEvent::Edited => Event::Edited {
1821                singleton_buffer_edited: true,
1822            },
1823            language::BufferEvent::DirtyChanged => Event::DirtyChanged,
1824            language::BufferEvent::Saved => Event::Saved,
1825            language::BufferEvent::FileHandleChanged => Event::FileHandleChanged,
1826            language::BufferEvent::Reloaded => Event::Reloaded,
1827            language::BufferEvent::ReloadNeeded => Event::ReloadNeeded,
1828            language::BufferEvent::DiffBaseChanged => Event::DiffBaseChanged,
1829            language::BufferEvent::DiffUpdated => Event::DiffUpdated { buffer },
1830            language::BufferEvent::LanguageChanged => {
1831                Event::LanguageChanged(buffer.read(cx).remote_id())
1832            }
1833            language::BufferEvent::Reparsed => Event::Reparsed(buffer.read(cx).remote_id()),
1834            language::BufferEvent::DiagnosticsUpdated => Event::DiagnosticsUpdated,
1835            language::BufferEvent::Closed => Event::Closed,
1836            language::BufferEvent::Discarded => Event::Discarded,
1837            language::BufferEvent::CapabilityChanged => {
1838                self.capability = buffer.read(cx).capability();
1839                Event::CapabilityChanged
1840            }
1841            //
1842            language::BufferEvent::Operation { .. } => return,
1843        });
1844    }
1845
1846    pub fn all_buffers(&self) -> HashSet<Model<Buffer>> {
1847        self.buffers
1848            .borrow()
1849            .values()
1850            .map(|state| state.buffer.clone())
1851            .collect()
1852    }
1853
1854    pub fn buffer(&self, buffer_id: BufferId) -> Option<Model<Buffer>> {
1855        self.buffers
1856            .borrow()
1857            .get(&buffer_id)
1858            .map(|state| state.buffer.clone())
1859    }
1860
1861    pub fn language_at<T: ToOffset>(&self, point: T, cx: &AppContext) -> Option<Arc<Language>> {
1862        self.point_to_buffer_offset(point, cx)
1863            .and_then(|(buffer, offset, _)| buffer.read(cx).language_at(offset))
1864    }
1865
1866    pub fn settings_at<'a, T: ToOffset>(
1867        &self,
1868        point: T,
1869        cx: &'a AppContext,
1870    ) -> Cow<'a, LanguageSettings> {
1871        let mut language = None;
1872        let mut file = None;
1873        if let Some((buffer, offset, _)) = self.point_to_buffer_offset(point, cx) {
1874            let buffer = buffer.read(cx);
1875            language = buffer.language_at(offset);
1876            file = buffer.file();
1877        }
1878        language_settings(language.map(|l| l.name()), file, cx)
1879    }
1880
1881    pub fn for_each_buffer(&self, mut f: impl FnMut(&Model<Buffer>)) {
1882        self.buffers
1883            .borrow()
1884            .values()
1885            .for_each(|state| f(&state.buffer))
1886    }
1887
1888    pub fn title<'a>(&'a self, cx: &'a AppContext) -> Cow<'a, str> {
1889        if let Some(title) = self.title.as_ref() {
1890            return title.into();
1891        }
1892
1893        if let Some(buffer) = self.as_singleton() {
1894            if let Some(file) = buffer.read(cx).file() {
1895                return file.file_name(cx).to_string_lossy();
1896            }
1897        }
1898
1899        "untitled".into()
1900    }
1901
1902    pub fn set_title(&mut self, title: String, cx: &mut ModelContext<Self>) {
1903        self.title = Some(title);
1904        cx.notify();
1905    }
1906
1907    /// Preserve preview tabs containing this multibuffer until additional edits occur.
1908    pub fn refresh_preview(&self, cx: &mut ModelContext<Self>) {
1909        for buffer_state in self.buffers.borrow().values() {
1910            buffer_state
1911                .buffer
1912                .update(cx, |buffer, _cx| buffer.refresh_preview());
1913        }
1914    }
1915
1916    /// Whether we should preserve the preview status of a tab containing this multi-buffer.
1917    pub fn preserve_preview(&self, cx: &AppContext) -> bool {
1918        self.buffers
1919            .borrow()
1920            .values()
1921            .all(|state| state.buffer.read(cx).preserve_preview())
1922    }
1923
1924    #[cfg(any(test, feature = "test-support"))]
1925    pub fn is_parsing(&self, cx: &AppContext) -> bool {
1926        self.as_singleton().unwrap().read(cx).is_parsing()
1927    }
1928
1929    pub fn resize_excerpt(
1930        &mut self,
1931        id: ExcerptId,
1932        range: Range<text::Anchor>,
1933        cx: &mut ModelContext<Self>,
1934    ) {
1935        self.sync(cx);
1936
1937        let snapshot = self.snapshot(cx);
1938        let locator = snapshot.excerpt_locator_for_id(id);
1939        let mut new_excerpts = SumTree::default();
1940        let mut cursor = snapshot.excerpts.cursor::<(Option<&Locator>, usize)>(&());
1941        let mut edits = Vec::<Edit<usize>>::new();
1942
1943        let prefix = cursor.slice(&Some(locator), Bias::Left, &());
1944        new_excerpts.append(prefix, &());
1945
1946        let mut excerpt = cursor.item().unwrap().clone();
1947        let old_text_len = excerpt.text_summary.len;
1948
1949        excerpt.range.context.start = range.start;
1950        excerpt.range.context.end = range.end;
1951        excerpt.max_buffer_row = range.end.to_point(&excerpt.buffer).row;
1952
1953        excerpt.text_summary = excerpt
1954            .buffer
1955            .text_summary_for_range(excerpt.range.context.clone());
1956
1957        let new_start_offset = new_excerpts.summary().text.len;
1958        let old_start_offset = cursor.start().1;
1959        let edit = Edit {
1960            old: old_start_offset..old_start_offset + old_text_len,
1961            new: new_start_offset..new_start_offset + excerpt.text_summary.len,
1962        };
1963
1964        if let Some(last_edit) = edits.last_mut() {
1965            if last_edit.old.end == edit.old.start {
1966                last_edit.old.end = edit.old.end;
1967                last_edit.new.end = edit.new.end;
1968            } else {
1969                edits.push(edit);
1970            }
1971        } else {
1972            edits.push(edit);
1973        }
1974
1975        new_excerpts.push(excerpt, &());
1976
1977        cursor.next(&());
1978
1979        new_excerpts.append(cursor.suffix(&()), &());
1980
1981        drop(cursor);
1982        self.snapshot.borrow_mut().excerpts = new_excerpts;
1983
1984        self.subscriptions.publish_mut(edits);
1985        cx.emit(Event::Edited {
1986            singleton_buffer_edited: false,
1987        });
1988        cx.emit(Event::ExcerptsExpanded { ids: vec![id] });
1989        cx.notify();
1990    }
1991
1992    pub fn expand_excerpts(
1993        &mut self,
1994        ids: impl IntoIterator<Item = ExcerptId>,
1995        line_count: u32,
1996        direction: ExpandExcerptDirection,
1997        cx: &mut ModelContext<Self>,
1998    ) {
1999        if line_count == 0 {
2000            return;
2001        }
2002        self.sync(cx);
2003
2004        let ids = ids.into_iter().collect::<Vec<_>>();
2005        let snapshot = self.snapshot(cx);
2006        let locators = snapshot.excerpt_locators_for_ids(ids.iter().copied());
2007        let mut new_excerpts = SumTree::default();
2008        let mut cursor = snapshot.excerpts.cursor::<(Option<&Locator>, usize)>(&());
2009        let mut edits = Vec::<Edit<usize>>::new();
2010
2011        for locator in &locators {
2012            let prefix = cursor.slice(&Some(locator), Bias::Left, &());
2013            new_excerpts.append(prefix, &());
2014
2015            let mut excerpt = cursor.item().unwrap().clone();
2016            let old_text_len = excerpt.text_summary.len;
2017
2018            let up_line_count = if direction.should_expand_up() {
2019                line_count
2020            } else {
2021                0
2022            };
2023
2024            let start_row = excerpt
2025                .range
2026                .context
2027                .start
2028                .to_point(&excerpt.buffer)
2029                .row
2030                .saturating_sub(up_line_count);
2031            let start_point = Point::new(start_row, 0);
2032            excerpt.range.context.start = excerpt.buffer.anchor_before(start_point);
2033
2034            let down_line_count = if direction.should_expand_down() {
2035                line_count
2036            } else {
2037                0
2038            };
2039
2040            let mut end_point = excerpt.buffer.clip_point(
2041                excerpt.range.context.end.to_point(&excerpt.buffer)
2042                    + Point::new(down_line_count, 0),
2043                Bias::Left,
2044            );
2045            end_point.column = excerpt.buffer.line_len(end_point.row);
2046            excerpt.range.context.end = excerpt.buffer.anchor_after(end_point);
2047            excerpt.max_buffer_row = end_point.row;
2048
2049            excerpt.text_summary = excerpt
2050                .buffer
2051                .text_summary_for_range(excerpt.range.context.clone());
2052
2053            let new_start_offset = new_excerpts.summary().text.len;
2054            let old_start_offset = cursor.start().1;
2055            let edit = Edit {
2056                old: old_start_offset..old_start_offset + old_text_len,
2057                new: new_start_offset..new_start_offset + excerpt.text_summary.len,
2058            };
2059
2060            if let Some(last_edit) = edits.last_mut() {
2061                if last_edit.old.end == edit.old.start {
2062                    last_edit.old.end = edit.old.end;
2063                    last_edit.new.end = edit.new.end;
2064                } else {
2065                    edits.push(edit);
2066                }
2067            } else {
2068                edits.push(edit);
2069            }
2070
2071            new_excerpts.push(excerpt, &());
2072
2073            cursor.next(&());
2074        }
2075
2076        new_excerpts.append(cursor.suffix(&()), &());
2077
2078        drop(cursor);
2079        self.snapshot.borrow_mut().excerpts = new_excerpts;
2080
2081        self.subscriptions.publish_mut(edits);
2082        cx.emit(Event::Edited {
2083            singleton_buffer_edited: false,
2084        });
2085        cx.emit(Event::ExcerptsExpanded { ids });
2086        cx.notify();
2087    }
2088
2089    fn sync(&self, cx: &AppContext) {
2090        let mut snapshot = self.snapshot.borrow_mut();
2091        let mut excerpts_to_edit = Vec::new();
2092        let mut non_text_state_updated = false;
2093        let mut is_dirty = false;
2094        let mut has_deleted_file = false;
2095        let mut has_conflict = false;
2096        let mut edited = false;
2097        let mut buffers = self.buffers.borrow_mut();
2098        for buffer_state in buffers.values_mut() {
2099            let buffer = buffer_state.buffer.read(cx);
2100            let version = buffer.version();
2101            let non_text_state_update_count = buffer.non_text_state_update_count();
2102
2103            let buffer_edited = version.changed_since(&buffer_state.last_version);
2104            let buffer_non_text_state_updated =
2105                non_text_state_update_count > buffer_state.last_non_text_state_update_count;
2106            if buffer_edited || buffer_non_text_state_updated {
2107                buffer_state.last_version = version;
2108                buffer_state.last_non_text_state_update_count = non_text_state_update_count;
2109                excerpts_to_edit.extend(
2110                    buffer_state
2111                        .excerpts
2112                        .iter()
2113                        .map(|locator| (locator, buffer_state.buffer.clone(), buffer_edited)),
2114                );
2115            }
2116
2117            edited |= buffer_edited;
2118            non_text_state_updated |= buffer_non_text_state_updated;
2119            is_dirty |= buffer.is_dirty();
2120            has_deleted_file |= buffer
2121                .file()
2122                .map_or(false, |file| file.disk_state() == DiskState::Deleted);
2123            has_conflict |= buffer.has_conflict();
2124        }
2125        if edited {
2126            snapshot.edit_count += 1;
2127        }
2128        if non_text_state_updated {
2129            snapshot.non_text_state_update_count += 1;
2130        }
2131        snapshot.is_dirty = is_dirty;
2132        snapshot.has_deleted_file = has_deleted_file;
2133        snapshot.has_conflict = has_conflict;
2134
2135        excerpts_to_edit.sort_unstable_by_key(|(locator, _, _)| *locator);
2136
2137        let mut edits = Vec::new();
2138        let mut new_excerpts = SumTree::default();
2139        let mut cursor = snapshot.excerpts.cursor::<(Option<&Locator>, usize)>(&());
2140
2141        for (locator, buffer, buffer_edited) in excerpts_to_edit {
2142            new_excerpts.append(cursor.slice(&Some(locator), Bias::Left, &()), &());
2143            let old_excerpt = cursor.item().unwrap();
2144            let buffer = buffer.read(cx);
2145            let buffer_id = buffer.remote_id();
2146
2147            let mut new_excerpt;
2148            if buffer_edited {
2149                edits.extend(
2150                    buffer
2151                        .edits_since_in_range::<usize>(
2152                            old_excerpt.buffer.version(),
2153                            old_excerpt.range.context.clone(),
2154                        )
2155                        .map(|mut edit| {
2156                            let excerpt_old_start = cursor.start().1;
2157                            let excerpt_new_start = new_excerpts.summary().text.len;
2158                            edit.old.start += excerpt_old_start;
2159                            edit.old.end += excerpt_old_start;
2160                            edit.new.start += excerpt_new_start;
2161                            edit.new.end += excerpt_new_start;
2162                            edit
2163                        }),
2164                );
2165
2166                new_excerpt = Excerpt::new(
2167                    old_excerpt.id,
2168                    locator.clone(),
2169                    buffer_id,
2170                    buffer.snapshot(),
2171                    old_excerpt.range.clone(),
2172                    old_excerpt.has_trailing_newline,
2173                );
2174            } else {
2175                new_excerpt = old_excerpt.clone();
2176                new_excerpt.buffer = buffer.snapshot();
2177            }
2178
2179            new_excerpts.push(new_excerpt, &());
2180            cursor.next(&());
2181        }
2182        new_excerpts.append(cursor.suffix(&()), &());
2183
2184        drop(cursor);
2185        snapshot.excerpts = new_excerpts;
2186
2187        self.subscriptions.publish(edits);
2188    }
2189}
2190
2191#[cfg(any(test, feature = "test-support"))]
2192impl MultiBuffer {
2193    pub fn build_simple(text: &str, cx: &mut gpui::AppContext) -> Model<Self> {
2194        let buffer = cx.new_model(|cx| Buffer::local(text, cx));
2195        cx.new_model(|cx| Self::singleton(buffer, cx))
2196    }
2197
2198    pub fn build_multi<const COUNT: usize>(
2199        excerpts: [(&str, Vec<Range<Point>>); COUNT],
2200        cx: &mut gpui::AppContext,
2201    ) -> Model<Self> {
2202        let multi = cx.new_model(|_| Self::new(Capability::ReadWrite));
2203        for (text, ranges) in excerpts {
2204            let buffer = cx.new_model(|cx| Buffer::local(text, cx));
2205            let excerpt_ranges = ranges.into_iter().map(|range| ExcerptRange {
2206                context: range,
2207                primary: None,
2208            });
2209            multi.update(cx, |multi, cx| {
2210                multi.push_excerpts(buffer, excerpt_ranges, cx)
2211            });
2212        }
2213
2214        multi
2215    }
2216
2217    pub fn build_from_buffer(buffer: Model<Buffer>, cx: &mut gpui::AppContext) -> Model<Self> {
2218        cx.new_model(|cx| Self::singleton(buffer, cx))
2219    }
2220
2221    pub fn build_random(rng: &mut impl rand::Rng, cx: &mut gpui::AppContext) -> Model<Self> {
2222        cx.new_model(|cx| {
2223            let mut multibuffer = MultiBuffer::new(Capability::ReadWrite);
2224            let mutation_count = rng.gen_range(1..=5);
2225            multibuffer.randomly_edit_excerpts(rng, mutation_count, cx);
2226            multibuffer
2227        })
2228    }
2229
2230    pub fn randomly_edit(
2231        &mut self,
2232        rng: &mut impl rand::Rng,
2233        edit_count: usize,
2234        cx: &mut ModelContext<Self>,
2235    ) {
2236        use util::RandomCharIter;
2237
2238        let snapshot = self.read(cx);
2239        let mut edits: Vec<(Range<usize>, Arc<str>)> = Vec::new();
2240        let mut last_end = None;
2241        for _ in 0..edit_count {
2242            if last_end.map_or(false, |last_end| last_end >= snapshot.len()) {
2243                break;
2244            }
2245
2246            let new_start = last_end.map_or(0, |last_end| last_end + 1);
2247            let end = snapshot.clip_offset(rng.gen_range(new_start..=snapshot.len()), Bias::Right);
2248            let start = snapshot.clip_offset(rng.gen_range(new_start..=end), Bias::Right);
2249            last_end = Some(end);
2250
2251            let mut range = start..end;
2252            if rng.gen_bool(0.2) {
2253                mem::swap(&mut range.start, &mut range.end);
2254            }
2255
2256            let new_text_len = rng.gen_range(0..10);
2257            let new_text: String = RandomCharIter::new(&mut *rng).take(new_text_len).collect();
2258
2259            edits.push((range, new_text.into()));
2260        }
2261        log::info!("mutating multi-buffer with {:?}", edits);
2262        drop(snapshot);
2263
2264        self.edit(edits, None, cx);
2265    }
2266
2267    pub fn randomly_edit_excerpts(
2268        &mut self,
2269        rng: &mut impl rand::Rng,
2270        mutation_count: usize,
2271        cx: &mut ModelContext<Self>,
2272    ) {
2273        use rand::prelude::*;
2274        use std::env;
2275        use util::RandomCharIter;
2276
2277        let max_excerpts = env::var("MAX_EXCERPTS")
2278            .map(|i| i.parse().expect("invalid `MAX_EXCERPTS` variable"))
2279            .unwrap_or(5);
2280
2281        let mut buffers = Vec::new();
2282        for _ in 0..mutation_count {
2283            if rng.gen_bool(0.05) {
2284                log::info!("Clearing multi-buffer");
2285                self.clear(cx);
2286                continue;
2287            } else if rng.gen_bool(0.1) && !self.excerpt_ids().is_empty() {
2288                let ids = self.excerpt_ids();
2289                let mut excerpts = HashSet::default();
2290                for _ in 0..rng.gen_range(0..ids.len()) {
2291                    excerpts.extend(ids.choose(rng).copied());
2292                }
2293
2294                let line_count = rng.gen_range(0..5);
2295
2296                log::info!("Expanding excerpts {excerpts:?} by {line_count} lines");
2297
2298                self.expand_excerpts(
2299                    excerpts.iter().cloned(),
2300                    line_count,
2301                    ExpandExcerptDirection::UpAndDown,
2302                    cx,
2303                );
2304                continue;
2305            }
2306
2307            let excerpt_ids = self.excerpt_ids();
2308            if excerpt_ids.is_empty() || (rng.gen() && excerpt_ids.len() < max_excerpts) {
2309                let buffer_handle = if rng.gen() || self.buffers.borrow().is_empty() {
2310                    let text = RandomCharIter::new(&mut *rng).take(10).collect::<String>();
2311                    buffers.push(cx.new_model(|cx| Buffer::local(text, cx)));
2312                    let buffer = buffers.last().unwrap().read(cx);
2313                    log::info!(
2314                        "Creating new buffer {} with text: {:?}",
2315                        buffer.remote_id(),
2316                        buffer.text()
2317                    );
2318                    buffers.last().unwrap().clone()
2319                } else {
2320                    self.buffers
2321                        .borrow()
2322                        .values()
2323                        .choose(rng)
2324                        .unwrap()
2325                        .buffer
2326                        .clone()
2327                };
2328
2329                let buffer = buffer_handle.read(cx);
2330                let buffer_text = buffer.text();
2331                let ranges = (0..rng.gen_range(0..5))
2332                    .map(|_| {
2333                        let end_ix =
2334                            buffer.clip_offset(rng.gen_range(0..=buffer.len()), Bias::Right);
2335                        let start_ix = buffer.clip_offset(rng.gen_range(0..=end_ix), Bias::Left);
2336                        ExcerptRange {
2337                            context: start_ix..end_ix,
2338                            primary: None,
2339                        }
2340                    })
2341                    .collect::<Vec<_>>();
2342                log::info!(
2343                    "Inserting excerpts from buffer {} and ranges {:?}: {:?}",
2344                    buffer_handle.read(cx).remote_id(),
2345                    ranges.iter().map(|r| &r.context).collect::<Vec<_>>(),
2346                    ranges
2347                        .iter()
2348                        .map(|r| &buffer_text[r.context.clone()])
2349                        .collect::<Vec<_>>()
2350                );
2351
2352                let excerpt_id = self.push_excerpts(buffer_handle.clone(), ranges, cx);
2353                log::info!("Inserted with ids: {:?}", excerpt_id);
2354            } else {
2355                let remove_count = rng.gen_range(1..=excerpt_ids.len());
2356                let mut excerpts_to_remove = excerpt_ids
2357                    .choose_multiple(rng, remove_count)
2358                    .cloned()
2359                    .collect::<Vec<_>>();
2360                let snapshot = self.snapshot.borrow();
2361                excerpts_to_remove.sort_unstable_by(|a, b| a.cmp(b, &snapshot));
2362                drop(snapshot);
2363                log::info!("Removing excerpts {:?}", excerpts_to_remove);
2364                self.remove_excerpts(excerpts_to_remove, cx);
2365            }
2366        }
2367    }
2368
2369    pub fn randomly_mutate(
2370        &mut self,
2371        rng: &mut impl rand::Rng,
2372        mutation_count: usize,
2373        cx: &mut ModelContext<Self>,
2374    ) {
2375        use rand::prelude::*;
2376
2377        if rng.gen_bool(0.7) || self.singleton {
2378            let buffer = self
2379                .buffers
2380                .borrow()
2381                .values()
2382                .choose(rng)
2383                .map(|state| state.buffer.clone());
2384
2385            if let Some(buffer) = buffer {
2386                buffer.update(cx, |buffer, cx| {
2387                    if rng.gen() {
2388                        buffer.randomly_edit(rng, mutation_count, cx);
2389                    } else {
2390                        buffer.randomly_undo_redo(rng, cx);
2391                    }
2392                });
2393            } else {
2394                self.randomly_edit(rng, mutation_count, cx);
2395            }
2396        } else {
2397            self.randomly_edit_excerpts(rng, mutation_count, cx);
2398        }
2399
2400        self.check_invariants(cx);
2401    }
2402
2403    fn check_invariants(&self, cx: &mut ModelContext<Self>) {
2404        let snapshot = self.read(cx);
2405        let excerpts = snapshot.excerpts.items(&());
2406        let excerpt_ids = snapshot.excerpt_ids.items(&());
2407
2408        for (ix, excerpt) in excerpts.iter().enumerate() {
2409            if ix == 0 {
2410                if excerpt.locator <= Locator::min() {
2411                    panic!("invalid first excerpt locator {:?}", excerpt.locator);
2412                }
2413            } else if excerpt.locator <= excerpts[ix - 1].locator {
2414                panic!("excerpts are out-of-order: {:?}", excerpts);
2415            }
2416        }
2417
2418        for (ix, entry) in excerpt_ids.iter().enumerate() {
2419            if ix == 0 {
2420                if entry.id.cmp(&ExcerptId::min(), &snapshot).is_le() {
2421                    panic!("invalid first excerpt id {:?}", entry.id);
2422                }
2423            } else if entry.id <= excerpt_ids[ix - 1].id {
2424                panic!("excerpt ids are out-of-order: {:?}", excerpt_ids);
2425            }
2426        }
2427    }
2428}
2429
2430impl EventEmitter<Event> for MultiBuffer {}
2431
2432impl MultiBufferSnapshot {
2433    pub fn text(&self) -> String {
2434        self.chunks(0..self.len(), false)
2435            .map(|chunk| chunk.text)
2436            .collect()
2437    }
2438
2439    pub fn reversed_chars_at<T: ToOffset>(&self, position: T) -> impl Iterator<Item = char> + '_ {
2440        let mut offset = position.to_offset(self);
2441        let mut cursor = self.excerpts.cursor::<usize>(&());
2442        cursor.seek(&offset, Bias::Left, &());
2443        let mut excerpt_chunks = cursor.item().map(|excerpt| {
2444            let end_before_footer = cursor.start() + excerpt.text_summary.len;
2445            let start = excerpt.range.context.start.to_offset(&excerpt.buffer);
2446            let end = start + (cmp::min(offset, end_before_footer) - cursor.start());
2447            excerpt.buffer.reversed_chunks_in_range(start..end)
2448        });
2449        iter::from_fn(move || {
2450            if offset == *cursor.start() {
2451                cursor.prev(&());
2452                let excerpt = cursor.item()?;
2453                excerpt_chunks = Some(
2454                    excerpt
2455                        .buffer
2456                        .reversed_chunks_in_range(excerpt.range.context.clone()),
2457                );
2458            }
2459
2460            let excerpt = cursor.item().unwrap();
2461            if offset == cursor.end(&()) && excerpt.has_trailing_newline {
2462                offset -= 1;
2463                Some("\n")
2464            } else {
2465                let chunk = excerpt_chunks.as_mut().unwrap().next().unwrap();
2466                offset -= chunk.len();
2467                Some(chunk)
2468            }
2469        })
2470        .flat_map(|c| c.chars().rev())
2471    }
2472
2473    pub fn chars_at<T: ToOffset>(&self, position: T) -> impl Iterator<Item = char> + '_ {
2474        let offset = position.to_offset(self);
2475        self.text_for_range(offset..self.len())
2476            .flat_map(|chunk| chunk.chars())
2477    }
2478
2479    pub fn text_for_range<T: ToOffset>(&self, range: Range<T>) -> impl Iterator<Item = &str> + '_ {
2480        self.chunks(range, false).map(|chunk| chunk.text)
2481    }
2482
2483    pub fn is_line_blank(&self, row: MultiBufferRow) -> bool {
2484        self.text_for_range(Point::new(row.0, 0)..Point::new(row.0, self.line_len(row)))
2485            .all(|chunk| chunk.matches(|c: char| !c.is_whitespace()).next().is_none())
2486    }
2487
2488    pub fn contains_str_at<T>(&self, position: T, needle: &str) -> bool
2489    where
2490        T: ToOffset,
2491    {
2492        let position = position.to_offset(self);
2493        position == self.clip_offset(position, Bias::Left)
2494            && self
2495                .bytes_in_range(position..self.len())
2496                .flatten()
2497                .copied()
2498                .take(needle.len())
2499                .eq(needle.bytes())
2500    }
2501
2502    pub fn surrounding_word<T: ToOffset>(
2503        &self,
2504        start: T,
2505        for_completion: bool,
2506    ) -> (Range<usize>, Option<CharKind>) {
2507        let mut start = start.to_offset(self);
2508        let mut end = start;
2509        let mut next_chars = self.chars_at(start).peekable();
2510        let mut prev_chars = self.reversed_chars_at(start).peekable();
2511
2512        let classifier = self
2513            .char_classifier_at(start)
2514            .for_completion(for_completion);
2515
2516        let word_kind = cmp::max(
2517            prev_chars.peek().copied().map(|c| classifier.kind(c)),
2518            next_chars.peek().copied().map(|c| classifier.kind(c)),
2519        );
2520
2521        for ch in prev_chars {
2522            if Some(classifier.kind(ch)) == word_kind && ch != '\n' {
2523                start -= ch.len_utf8();
2524            } else {
2525                break;
2526            }
2527        }
2528
2529        for ch in next_chars {
2530            if Some(classifier.kind(ch)) == word_kind && ch != '\n' {
2531                end += ch.len_utf8();
2532            } else {
2533                break;
2534            }
2535        }
2536
2537        (start..end, word_kind)
2538    }
2539
2540    pub fn as_singleton(&self) -> Option<(&ExcerptId, BufferId, &BufferSnapshot)> {
2541        if self.singleton {
2542            self.excerpts
2543                .iter()
2544                .next()
2545                .map(|e| (&e.id, e.buffer_id, &e.buffer))
2546        } else {
2547            None
2548        }
2549    }
2550
2551    pub fn len(&self) -> usize {
2552        self.excerpts.summary().text.len
2553    }
2554
2555    pub fn is_empty(&self) -> bool {
2556        self.excerpts.summary().text.len == 0
2557    }
2558
2559    pub fn max_buffer_row(&self) -> MultiBufferRow {
2560        self.excerpts.summary().max_buffer_row
2561    }
2562
2563    pub fn clip_offset(&self, offset: usize, bias: Bias) -> usize {
2564        if let Some((_, _, buffer)) = self.as_singleton() {
2565            return buffer.clip_offset(offset, bias);
2566        }
2567
2568        let mut cursor = self.excerpts.cursor::<usize>(&());
2569        cursor.seek(&offset, Bias::Right, &());
2570        let overshoot = if let Some(excerpt) = cursor.item() {
2571            let excerpt_start = excerpt.range.context.start.to_offset(&excerpt.buffer);
2572            let buffer_offset = excerpt
2573                .buffer
2574                .clip_offset(excerpt_start + (offset - cursor.start()), bias);
2575            buffer_offset.saturating_sub(excerpt_start)
2576        } else {
2577            0
2578        };
2579        cursor.start() + overshoot
2580    }
2581
2582    pub fn clip_point(&self, point: Point, bias: Bias) -> Point {
2583        if let Some((_, _, buffer)) = self.as_singleton() {
2584            return buffer.clip_point(point, bias);
2585        }
2586
2587        let mut cursor = self.excerpts.cursor::<Point>(&());
2588        cursor.seek(&point, Bias::Right, &());
2589        let overshoot = if let Some(excerpt) = cursor.item() {
2590            let excerpt_start = excerpt.range.context.start.to_point(&excerpt.buffer);
2591            let buffer_point = excerpt
2592                .buffer
2593                .clip_point(excerpt_start + (point - cursor.start()), bias);
2594            buffer_point.saturating_sub(excerpt_start)
2595        } else {
2596            Point::zero()
2597        };
2598        *cursor.start() + overshoot
2599    }
2600
2601    pub fn clip_offset_utf16(&self, offset: OffsetUtf16, bias: Bias) -> OffsetUtf16 {
2602        if let Some((_, _, buffer)) = self.as_singleton() {
2603            return buffer.clip_offset_utf16(offset, bias);
2604        }
2605
2606        let mut cursor = self.excerpts.cursor::<OffsetUtf16>(&());
2607        cursor.seek(&offset, Bias::Right, &());
2608        let overshoot = if let Some(excerpt) = cursor.item() {
2609            let excerpt_start = excerpt.range.context.start.to_offset_utf16(&excerpt.buffer);
2610            let buffer_offset = excerpt
2611                .buffer
2612                .clip_offset_utf16(excerpt_start + (offset - cursor.start()), bias);
2613            OffsetUtf16(buffer_offset.0.saturating_sub(excerpt_start.0))
2614        } else {
2615            OffsetUtf16(0)
2616        };
2617        *cursor.start() + overshoot
2618    }
2619
2620    pub fn clip_point_utf16(&self, point: Unclipped<PointUtf16>, bias: Bias) -> PointUtf16 {
2621        if let Some((_, _, buffer)) = self.as_singleton() {
2622            return buffer.clip_point_utf16(point, bias);
2623        }
2624
2625        let mut cursor = self.excerpts.cursor::<PointUtf16>(&());
2626        cursor.seek(&point.0, Bias::Right, &());
2627        let overshoot = if let Some(excerpt) = cursor.item() {
2628            let excerpt_start = excerpt
2629                .buffer
2630                .offset_to_point_utf16(excerpt.range.context.start.to_offset(&excerpt.buffer));
2631            let buffer_point = excerpt
2632                .buffer
2633                .clip_point_utf16(Unclipped(excerpt_start + (point.0 - cursor.start())), bias);
2634            buffer_point.saturating_sub(excerpt_start)
2635        } else {
2636            PointUtf16::zero()
2637        };
2638        *cursor.start() + overshoot
2639    }
2640
2641    pub fn bytes_in_range<T: ToOffset>(&self, range: Range<T>) -> MultiBufferBytes {
2642        let range = range.start.to_offset(self)..range.end.to_offset(self);
2643        let mut excerpts = self.excerpts.cursor::<usize>(&());
2644        excerpts.seek(&range.start, Bias::Right, &());
2645
2646        let mut chunk = &[][..];
2647        let excerpt_bytes = if let Some(excerpt) = excerpts.item() {
2648            let mut excerpt_bytes = excerpt
2649                .bytes_in_range(range.start - excerpts.start()..range.end - excerpts.start());
2650            chunk = excerpt_bytes.next().unwrap_or(&[][..]);
2651            Some(excerpt_bytes)
2652        } else {
2653            None
2654        };
2655        MultiBufferBytes {
2656            range,
2657            excerpts,
2658            excerpt_bytes,
2659            chunk,
2660        }
2661    }
2662
2663    pub fn reversed_bytes_in_range<T: ToOffset>(
2664        &self,
2665        range: Range<T>,
2666    ) -> ReversedMultiBufferBytes {
2667        let range = range.start.to_offset(self)..range.end.to_offset(self);
2668        let mut excerpts = self.excerpts.cursor::<usize>(&());
2669        excerpts.seek(&range.end, Bias::Left, &());
2670
2671        let mut chunk = &[][..];
2672        let excerpt_bytes = if let Some(excerpt) = excerpts.item() {
2673            let mut excerpt_bytes = excerpt.reversed_bytes_in_range(
2674                range.start.saturating_sub(*excerpts.start())..range.end - *excerpts.start(),
2675            );
2676            chunk = excerpt_bytes.next().unwrap_or(&[][..]);
2677            Some(excerpt_bytes)
2678        } else {
2679            None
2680        };
2681
2682        ReversedMultiBufferBytes {
2683            range,
2684            excerpts,
2685            excerpt_bytes,
2686            chunk,
2687        }
2688    }
2689
2690    pub fn buffer_rows(&self, start_row: MultiBufferRow) -> MultiBufferRows {
2691        let mut result = MultiBufferRows {
2692            buffer_row_range: 0..0,
2693            excerpts: self.excerpts.cursor(&()),
2694        };
2695        result.seek(start_row);
2696        result
2697    }
2698
2699    pub fn chunks<T: ToOffset>(&self, range: Range<T>, language_aware: bool) -> MultiBufferChunks {
2700        let range = range.start.to_offset(self)..range.end.to_offset(self);
2701        let mut chunks = MultiBufferChunks {
2702            range: range.clone(),
2703            excerpts: self.excerpts.cursor(&()),
2704            excerpt_chunks: None,
2705            language_aware,
2706        };
2707        chunks.seek(range);
2708        chunks
2709    }
2710
2711    pub fn offset_to_point(&self, offset: usize) -> Point {
2712        if let Some((_, _, buffer)) = self.as_singleton() {
2713            return buffer.offset_to_point(offset);
2714        }
2715
2716        let mut cursor = self.excerpts.cursor::<(usize, Point)>(&());
2717        cursor.seek(&offset, Bias::Right, &());
2718        if let Some(excerpt) = cursor.item() {
2719            let (start_offset, start_point) = cursor.start();
2720            let overshoot = offset - start_offset;
2721            let excerpt_start_offset = excerpt.range.context.start.to_offset(&excerpt.buffer);
2722            let excerpt_start_point = excerpt.range.context.start.to_point(&excerpt.buffer);
2723            let buffer_point = excerpt
2724                .buffer
2725                .offset_to_point(excerpt_start_offset + overshoot);
2726            *start_point + (buffer_point - excerpt_start_point)
2727        } else {
2728            self.excerpts.summary().text.lines
2729        }
2730    }
2731
2732    pub fn offset_to_point_utf16(&self, offset: usize) -> PointUtf16 {
2733        if let Some((_, _, buffer)) = self.as_singleton() {
2734            return buffer.offset_to_point_utf16(offset);
2735        }
2736
2737        let mut cursor = self.excerpts.cursor::<(usize, PointUtf16)>(&());
2738        cursor.seek(&offset, Bias::Right, &());
2739        if let Some(excerpt) = cursor.item() {
2740            let (start_offset, start_point) = cursor.start();
2741            let overshoot = offset - start_offset;
2742            let excerpt_start_offset = excerpt.range.context.start.to_offset(&excerpt.buffer);
2743            let excerpt_start_point = excerpt.range.context.start.to_point_utf16(&excerpt.buffer);
2744            let buffer_point = excerpt
2745                .buffer
2746                .offset_to_point_utf16(excerpt_start_offset + overshoot);
2747            *start_point + (buffer_point - excerpt_start_point)
2748        } else {
2749            self.excerpts.summary().text.lines_utf16()
2750        }
2751    }
2752
2753    pub fn point_to_point_utf16(&self, point: Point) -> PointUtf16 {
2754        if let Some((_, _, buffer)) = self.as_singleton() {
2755            return buffer.point_to_point_utf16(point);
2756        }
2757
2758        let mut cursor = self.excerpts.cursor::<(Point, PointUtf16)>(&());
2759        cursor.seek(&point, Bias::Right, &());
2760        if let Some(excerpt) = cursor.item() {
2761            let (start_offset, start_point) = cursor.start();
2762            let overshoot = point - start_offset;
2763            let excerpt_start_point = excerpt.range.context.start.to_point(&excerpt.buffer);
2764            let excerpt_start_point_utf16 =
2765                excerpt.range.context.start.to_point_utf16(&excerpt.buffer);
2766            let buffer_point = excerpt
2767                .buffer
2768                .point_to_point_utf16(excerpt_start_point + overshoot);
2769            *start_point + (buffer_point - excerpt_start_point_utf16)
2770        } else {
2771            self.excerpts.summary().text.lines_utf16()
2772        }
2773    }
2774
2775    pub fn point_to_offset(&self, point: Point) -> usize {
2776        if let Some((_, _, buffer)) = self.as_singleton() {
2777            return buffer.point_to_offset(point);
2778        }
2779
2780        let mut cursor = self.excerpts.cursor::<(Point, usize)>(&());
2781        cursor.seek(&point, Bias::Right, &());
2782        if let Some(excerpt) = cursor.item() {
2783            let (start_point, start_offset) = cursor.start();
2784            let overshoot = point - start_point;
2785            let excerpt_start_offset = excerpt.range.context.start.to_offset(&excerpt.buffer);
2786            let excerpt_start_point = excerpt.range.context.start.to_point(&excerpt.buffer);
2787            let buffer_offset = excerpt
2788                .buffer
2789                .point_to_offset(excerpt_start_point + overshoot);
2790            *start_offset + buffer_offset - excerpt_start_offset
2791        } else {
2792            self.excerpts.summary().text.len
2793        }
2794    }
2795
2796    pub fn offset_utf16_to_offset(&self, offset_utf16: OffsetUtf16) -> usize {
2797        if let Some((_, _, buffer)) = self.as_singleton() {
2798            return buffer.offset_utf16_to_offset(offset_utf16);
2799        }
2800
2801        let mut cursor = self.excerpts.cursor::<(OffsetUtf16, usize)>(&());
2802        cursor.seek(&offset_utf16, Bias::Right, &());
2803        if let Some(excerpt) = cursor.item() {
2804            let (start_offset_utf16, start_offset) = cursor.start();
2805            let overshoot = offset_utf16 - start_offset_utf16;
2806            let excerpt_start_offset = excerpt.range.context.start.to_offset(&excerpt.buffer);
2807            let excerpt_start_offset_utf16 =
2808                excerpt.buffer.offset_to_offset_utf16(excerpt_start_offset);
2809            let buffer_offset = excerpt
2810                .buffer
2811                .offset_utf16_to_offset(excerpt_start_offset_utf16 + overshoot);
2812            *start_offset + (buffer_offset - excerpt_start_offset)
2813        } else {
2814            self.excerpts.summary().text.len
2815        }
2816    }
2817
2818    pub fn offset_to_offset_utf16(&self, offset: usize) -> OffsetUtf16 {
2819        if let Some((_, _, buffer)) = self.as_singleton() {
2820            return buffer.offset_to_offset_utf16(offset);
2821        }
2822
2823        let mut cursor = self.excerpts.cursor::<(usize, OffsetUtf16)>(&());
2824        cursor.seek(&offset, Bias::Right, &());
2825        if let Some(excerpt) = cursor.item() {
2826            let (start_offset, start_offset_utf16) = cursor.start();
2827            let overshoot = offset - start_offset;
2828            let excerpt_start_offset_utf16 =
2829                excerpt.range.context.start.to_offset_utf16(&excerpt.buffer);
2830            let excerpt_start_offset = excerpt
2831                .buffer
2832                .offset_utf16_to_offset(excerpt_start_offset_utf16);
2833            let buffer_offset_utf16 = excerpt
2834                .buffer
2835                .offset_to_offset_utf16(excerpt_start_offset + overshoot);
2836            *start_offset_utf16 + (buffer_offset_utf16 - excerpt_start_offset_utf16)
2837        } else {
2838            self.excerpts.summary().text.len_utf16
2839        }
2840    }
2841
2842    pub fn point_utf16_to_offset(&self, point: PointUtf16) -> usize {
2843        if let Some((_, _, buffer)) = self.as_singleton() {
2844            return buffer.point_utf16_to_offset(point);
2845        }
2846
2847        let mut cursor = self.excerpts.cursor::<(PointUtf16, usize)>(&());
2848        cursor.seek(&point, Bias::Right, &());
2849        if let Some(excerpt) = cursor.item() {
2850            let (start_point, start_offset) = cursor.start();
2851            let overshoot = point - start_point;
2852            let excerpt_start_offset = excerpt.range.context.start.to_offset(&excerpt.buffer);
2853            let excerpt_start_point = excerpt
2854                .buffer
2855                .offset_to_point_utf16(excerpt.range.context.start.to_offset(&excerpt.buffer));
2856            let buffer_offset = excerpt
2857                .buffer
2858                .point_utf16_to_offset(excerpt_start_point + overshoot);
2859            *start_offset + (buffer_offset - excerpt_start_offset)
2860        } else {
2861            self.excerpts.summary().text.len
2862        }
2863    }
2864
2865    pub fn point_to_buffer_offset<T: ToOffset>(
2866        &self,
2867        point: T,
2868    ) -> Option<(&BufferSnapshot, usize)> {
2869        let offset = point.to_offset(self);
2870        let mut cursor = self.excerpts.cursor::<usize>(&());
2871        cursor.seek(&offset, Bias::Right, &());
2872        if cursor.item().is_none() {
2873            cursor.prev(&());
2874        }
2875
2876        cursor.item().map(|excerpt| {
2877            let excerpt_start = excerpt.range.context.start.to_offset(&excerpt.buffer);
2878            let buffer_point = excerpt_start + offset - *cursor.start();
2879            (&excerpt.buffer, buffer_point)
2880        })
2881    }
2882
2883    pub fn suggested_indents(
2884        &self,
2885        rows: impl IntoIterator<Item = u32>,
2886        cx: &AppContext,
2887    ) -> BTreeMap<MultiBufferRow, IndentSize> {
2888        let mut result = BTreeMap::new();
2889
2890        let mut rows_for_excerpt = Vec::new();
2891        let mut cursor = self.excerpts.cursor::<Point>(&());
2892        let mut rows = rows.into_iter().peekable();
2893        let mut prev_row = u32::MAX;
2894        let mut prev_language_indent_size = IndentSize::default();
2895
2896        while let Some(row) = rows.next() {
2897            cursor.seek(&Point::new(row, 0), Bias::Right, &());
2898            let excerpt = match cursor.item() {
2899                Some(excerpt) => excerpt,
2900                _ => continue,
2901            };
2902
2903            // Retrieve the language and indent size once for each disjoint region being indented.
2904            let single_indent_size = if row.saturating_sub(1) == prev_row {
2905                prev_language_indent_size
2906            } else {
2907                excerpt
2908                    .buffer
2909                    .language_indent_size_at(Point::new(row, 0), cx)
2910            };
2911            prev_language_indent_size = single_indent_size;
2912            prev_row = row;
2913
2914            let start_buffer_row = excerpt.range.context.start.to_point(&excerpt.buffer).row;
2915            let start_multibuffer_row = cursor.start().row;
2916
2917            rows_for_excerpt.push(row);
2918            while let Some(next_row) = rows.peek().copied() {
2919                if cursor.end(&()).row > next_row {
2920                    rows_for_excerpt.push(next_row);
2921                    rows.next();
2922                } else {
2923                    break;
2924                }
2925            }
2926
2927            let buffer_rows = rows_for_excerpt
2928                .drain(..)
2929                .map(|row| start_buffer_row + row - start_multibuffer_row);
2930            let buffer_indents = excerpt
2931                .buffer
2932                .suggested_indents(buffer_rows, single_indent_size);
2933            let multibuffer_indents = buffer_indents.into_iter().map(|(row, indent)| {
2934                (
2935                    MultiBufferRow(start_multibuffer_row + row - start_buffer_row),
2936                    indent,
2937                )
2938            });
2939            result.extend(multibuffer_indents);
2940        }
2941
2942        result
2943    }
2944
2945    pub fn indent_size_for_line(&self, row: MultiBufferRow) -> IndentSize {
2946        if let Some((buffer, range)) = self.buffer_line_for_row(row) {
2947            let mut size = buffer.indent_size_for_line(range.start.row);
2948            size.len = size
2949                .len
2950                .min(range.end.column)
2951                .saturating_sub(range.start.column);
2952            size
2953        } else {
2954            IndentSize::spaces(0)
2955        }
2956    }
2957
2958    pub fn indent_and_comment_for_line(&self, row: MultiBufferRow, cx: &AppContext) -> String {
2959        let mut indent = self.indent_size_for_line(row).chars().collect::<String>();
2960
2961        if self.settings_at(0, cx).extend_comment_on_newline {
2962            if let Some(language_scope) = self.language_scope_at(Point::new(row.0, 0)) {
2963                let delimiters = language_scope.line_comment_prefixes();
2964                for delimiter in delimiters {
2965                    if *self
2966                        .chars_at(Point::new(row.0, indent.len() as u32))
2967                        .take(delimiter.chars().count())
2968                        .collect::<String>()
2969                        .as_str()
2970                        == **delimiter
2971                    {
2972                        indent.push_str(&delimiter);
2973                        break;
2974                    }
2975                }
2976            }
2977        }
2978
2979        indent
2980    }
2981
2982    pub fn prev_non_blank_row(&self, mut row: MultiBufferRow) -> Option<MultiBufferRow> {
2983        while row.0 > 0 {
2984            row.0 -= 1;
2985            if !self.is_line_blank(row) {
2986                return Some(row);
2987            }
2988        }
2989        None
2990    }
2991
2992    pub fn line_len(&self, row: MultiBufferRow) -> u32 {
2993        if let Some((_, range)) = self.buffer_line_for_row(row) {
2994            range.end.column - range.start.column
2995        } else {
2996            0
2997        }
2998    }
2999
3000    pub fn buffer_line_for_row(
3001        &self,
3002        row: MultiBufferRow,
3003    ) -> Option<(&BufferSnapshot, Range<Point>)> {
3004        let mut cursor = self.excerpts.cursor::<Point>(&());
3005        let point = Point::new(row.0, 0);
3006        cursor.seek(&point, Bias::Right, &());
3007        if cursor.item().is_none() && *cursor.start() == point {
3008            cursor.prev(&());
3009        }
3010        if let Some(excerpt) = cursor.item() {
3011            let overshoot = row.0 - cursor.start().row;
3012            let excerpt_start = excerpt.range.context.start.to_point(&excerpt.buffer);
3013            let excerpt_end = excerpt.range.context.end.to_point(&excerpt.buffer);
3014            let buffer_row = excerpt_start.row + overshoot;
3015            let line_start = Point::new(buffer_row, 0);
3016            let line_end = Point::new(buffer_row, excerpt.buffer.line_len(buffer_row));
3017            return Some((
3018                &excerpt.buffer,
3019                line_start.max(excerpt_start)..line_end.min(excerpt_end),
3020            ));
3021        }
3022        None
3023    }
3024
3025    pub fn max_point(&self) -> Point {
3026        self.text_summary().lines
3027    }
3028
3029    pub fn text_summary(&self) -> TextSummary {
3030        self.excerpts.summary().text.clone()
3031    }
3032
3033    pub fn text_summary_for_range<D, O>(&self, range: Range<O>) -> D
3034    where
3035        D: TextDimension,
3036        O: ToOffset,
3037    {
3038        let mut summary = D::zero(&());
3039        let mut range = range.start.to_offset(self)..range.end.to_offset(self);
3040        let mut cursor = self.excerpts.cursor::<usize>(&());
3041        cursor.seek(&range.start, Bias::Right, &());
3042        if let Some(excerpt) = cursor.item() {
3043            let mut end_before_newline = cursor.end(&());
3044            if excerpt.has_trailing_newline {
3045                end_before_newline -= 1;
3046            }
3047
3048            let excerpt_start = excerpt.range.context.start.to_offset(&excerpt.buffer);
3049            let start_in_excerpt = excerpt_start + (range.start - cursor.start());
3050            let end_in_excerpt =
3051                excerpt_start + (cmp::min(end_before_newline, range.end) - cursor.start());
3052            summary.add_assign(
3053                &excerpt
3054                    .buffer
3055                    .text_summary_for_range(start_in_excerpt..end_in_excerpt),
3056            );
3057
3058            if range.end > end_before_newline {
3059                summary.add_assign(&D::from_text_summary(&TextSummary::from("\n")));
3060            }
3061
3062            cursor.next(&());
3063        }
3064
3065        if range.end > *cursor.start() {
3066            summary.add_assign(&D::from_text_summary(&cursor.summary::<_, TextSummary>(
3067                &range.end,
3068                Bias::Right,
3069                &(),
3070            )));
3071            if let Some(excerpt) = cursor.item() {
3072                range.end = cmp::max(*cursor.start(), range.end);
3073
3074                let excerpt_start = excerpt.range.context.start.to_offset(&excerpt.buffer);
3075                let end_in_excerpt = excerpt_start + (range.end - cursor.start());
3076                summary.add_assign(
3077                    &excerpt
3078                        .buffer
3079                        .text_summary_for_range(excerpt_start..end_in_excerpt),
3080                );
3081            }
3082        }
3083
3084        summary
3085    }
3086
3087    pub fn summary_for_anchor<D>(&self, anchor: &Anchor) -> D
3088    where
3089        D: TextDimension + Ord + Sub<D, Output = D>,
3090    {
3091        let mut cursor = self.excerpts.cursor::<ExcerptSummary>(&());
3092        let locator = self.excerpt_locator_for_id(anchor.excerpt_id);
3093
3094        cursor.seek(locator, Bias::Left, &());
3095        if cursor.item().is_none() {
3096            cursor.next(&());
3097        }
3098
3099        let mut position = D::from_text_summary(&cursor.start().text);
3100        if let Some(excerpt) = cursor.item() {
3101            if excerpt.id == anchor.excerpt_id {
3102                let excerpt_buffer_start =
3103                    excerpt.range.context.start.summary::<D>(&excerpt.buffer);
3104                let excerpt_buffer_end = excerpt.range.context.end.summary::<D>(&excerpt.buffer);
3105                let buffer_position = cmp::min(
3106                    excerpt_buffer_end,
3107                    anchor.text_anchor.summary::<D>(&excerpt.buffer),
3108                );
3109                if buffer_position > excerpt_buffer_start {
3110                    position.add_assign(&(buffer_position - excerpt_buffer_start));
3111                }
3112            }
3113        }
3114        position
3115    }
3116
3117    pub fn summaries_for_anchors<'a, D, I>(&'a self, anchors: I) -> Vec<D>
3118    where
3119        D: TextDimension + Ord + Sub<D, Output = D>,
3120        I: 'a + IntoIterator<Item = &'a Anchor>,
3121    {
3122        if let Some((_, _, buffer)) = self.as_singleton() {
3123            return buffer
3124                .summaries_for_anchors(anchors.into_iter().map(|a| &a.text_anchor))
3125                .collect();
3126        }
3127
3128        let mut anchors = anchors.into_iter().peekable();
3129        let mut cursor = self.excerpts.cursor::<ExcerptSummary>(&());
3130        let mut summaries = Vec::new();
3131        while let Some(anchor) = anchors.peek() {
3132            let excerpt_id = anchor.excerpt_id;
3133            let excerpt_anchors = iter::from_fn(|| {
3134                let anchor = anchors.peek()?;
3135                if anchor.excerpt_id == excerpt_id {
3136                    Some(&anchors.next().unwrap().text_anchor)
3137                } else {
3138                    None
3139                }
3140            });
3141
3142            let locator = self.excerpt_locator_for_id(excerpt_id);
3143            cursor.seek_forward(locator, Bias::Left, &());
3144            if cursor.item().is_none() {
3145                cursor.next(&());
3146            }
3147
3148            let position = D::from_text_summary(&cursor.start().text);
3149            if let Some(excerpt) = cursor.item() {
3150                if excerpt.id == excerpt_id {
3151                    let excerpt_buffer_start =
3152                        excerpt.range.context.start.summary::<D>(&excerpt.buffer);
3153                    let excerpt_buffer_end =
3154                        excerpt.range.context.end.summary::<D>(&excerpt.buffer);
3155                    summaries.extend(
3156                        excerpt
3157                            .buffer
3158                            .summaries_for_anchors::<D, _>(excerpt_anchors)
3159                            .map(move |summary| {
3160                                let summary = cmp::min(excerpt_buffer_end.clone(), summary);
3161                                let mut position = position.clone();
3162                                let excerpt_buffer_start = excerpt_buffer_start.clone();
3163                                if summary > excerpt_buffer_start {
3164                                    position.add_assign(&(summary - excerpt_buffer_start));
3165                                }
3166                                position
3167                            }),
3168                    );
3169                    continue;
3170                }
3171            }
3172
3173            summaries.extend(excerpt_anchors.map(|_| position.clone()));
3174        }
3175
3176        summaries
3177    }
3178
3179    pub fn dimensions_from_points<'a, D>(
3180        &'a self,
3181        points: impl 'a + IntoIterator<Item = Point>,
3182    ) -> impl 'a + Iterator<Item = D>
3183    where
3184        D: TextDimension,
3185    {
3186        let mut cursor = self.excerpts.cursor::<TextSummary>(&());
3187        let mut memoized_source_start: Option<Point> = None;
3188        let mut points = points.into_iter();
3189        std::iter::from_fn(move || {
3190            let point = points.next()?;
3191
3192            // Clear the memoized source start if the point is in a different excerpt than previous.
3193            if memoized_source_start.map_or(false, |_| point >= cursor.end(&()).lines) {
3194                memoized_source_start = None;
3195            }
3196
3197            // Now determine where the excerpt containing the point starts in its source buffer.
3198            // We'll use this value to calculate overshoot next.
3199            let source_start = if let Some(source_start) = memoized_source_start {
3200                source_start
3201            } else {
3202                cursor.seek_forward(&point, Bias::Right, &());
3203                if let Some(excerpt) = cursor.item() {
3204                    let source_start = excerpt.range.context.start.to_point(&excerpt.buffer);
3205                    memoized_source_start = Some(source_start);
3206                    source_start
3207                } else {
3208                    return Some(D::from_text_summary(cursor.start()));
3209                }
3210            };
3211
3212            // First, assume the output dimension is at least the start of the excerpt containing the point
3213            let mut output = D::from_text_summary(cursor.start());
3214
3215            // If the point lands within its excerpt, calculate and add the overshoot in dimension D.
3216            if let Some(excerpt) = cursor.item() {
3217                let overshoot = point - cursor.start().lines;
3218                if !overshoot.is_zero() {
3219                    let end_in_excerpt = source_start + overshoot;
3220                    output.add_assign(
3221                        &excerpt
3222                            .buffer
3223                            .text_summary_for_range::<D, _>(source_start..end_in_excerpt),
3224                    );
3225                }
3226            }
3227            Some(output)
3228        })
3229    }
3230
3231    pub fn refresh_anchors<'a, I>(&'a self, anchors: I) -> Vec<(usize, Anchor, bool)>
3232    where
3233        I: 'a + IntoIterator<Item = &'a Anchor>,
3234    {
3235        let mut anchors = anchors.into_iter().enumerate().peekable();
3236        let mut cursor = self.excerpts.cursor::<Option<&Locator>>(&());
3237        cursor.next(&());
3238
3239        let mut result = Vec::new();
3240
3241        while let Some((_, anchor)) = anchors.peek() {
3242            let old_excerpt_id = anchor.excerpt_id;
3243
3244            // Find the location where this anchor's excerpt should be.
3245            let old_locator = self.excerpt_locator_for_id(old_excerpt_id);
3246            cursor.seek_forward(&Some(old_locator), Bias::Left, &());
3247
3248            if cursor.item().is_none() {
3249                cursor.next(&());
3250            }
3251
3252            let next_excerpt = cursor.item();
3253            let prev_excerpt = cursor.prev_item();
3254
3255            // Process all of the anchors for this excerpt.
3256            while let Some((_, anchor)) = anchors.peek() {
3257                if anchor.excerpt_id != old_excerpt_id {
3258                    break;
3259                }
3260                let (anchor_ix, anchor) = anchors.next().unwrap();
3261                let mut anchor = *anchor;
3262
3263                // Leave min and max anchors unchanged if invalid or
3264                // if the old excerpt still exists at this location
3265                let mut kept_position = next_excerpt
3266                    .map_or(false, |e| e.id == old_excerpt_id && e.contains(&anchor))
3267                    || old_excerpt_id == ExcerptId::max()
3268                    || old_excerpt_id == ExcerptId::min();
3269
3270                // If the old excerpt no longer exists at this location, then attempt to
3271                // find an equivalent position for this anchor in an adjacent excerpt.
3272                if !kept_position {
3273                    for excerpt in [next_excerpt, prev_excerpt].iter().filter_map(|e| *e) {
3274                        if excerpt.contains(&anchor) {
3275                            anchor.excerpt_id = excerpt.id;
3276                            kept_position = true;
3277                            break;
3278                        }
3279                    }
3280                }
3281
3282                // If there's no adjacent excerpt that contains the anchor's position,
3283                // then report that the anchor has lost its position.
3284                if !kept_position {
3285                    anchor = if let Some(excerpt) = next_excerpt {
3286                        let mut text_anchor = excerpt
3287                            .range
3288                            .context
3289                            .start
3290                            .bias(anchor.text_anchor.bias, &excerpt.buffer);
3291                        if text_anchor
3292                            .cmp(&excerpt.range.context.end, &excerpt.buffer)
3293                            .is_gt()
3294                        {
3295                            text_anchor = excerpt.range.context.end;
3296                        }
3297                        Anchor {
3298                            buffer_id: Some(excerpt.buffer_id),
3299                            excerpt_id: excerpt.id,
3300                            text_anchor,
3301                        }
3302                    } else if let Some(excerpt) = prev_excerpt {
3303                        let mut text_anchor = excerpt
3304                            .range
3305                            .context
3306                            .end
3307                            .bias(anchor.text_anchor.bias, &excerpt.buffer);
3308                        if text_anchor
3309                            .cmp(&excerpt.range.context.start, &excerpt.buffer)
3310                            .is_lt()
3311                        {
3312                            text_anchor = excerpt.range.context.start;
3313                        }
3314                        Anchor {
3315                            buffer_id: Some(excerpt.buffer_id),
3316                            excerpt_id: excerpt.id,
3317                            text_anchor,
3318                        }
3319                    } else if anchor.text_anchor.bias == Bias::Left {
3320                        Anchor::min()
3321                    } else {
3322                        Anchor::max()
3323                    };
3324                }
3325
3326                result.push((anchor_ix, anchor, kept_position));
3327            }
3328        }
3329        result.sort_unstable_by(|a, b| a.1.cmp(&b.1, self));
3330        result
3331    }
3332
3333    pub fn anchor_before<T: ToOffset>(&self, position: T) -> Anchor {
3334        self.anchor_at(position, Bias::Left)
3335    }
3336
3337    pub fn anchor_after<T: ToOffset>(&self, position: T) -> Anchor {
3338        self.anchor_at(position, Bias::Right)
3339    }
3340
3341    pub fn anchor_at<T: ToOffset>(&self, position: T, mut bias: Bias) -> Anchor {
3342        let offset = position.to_offset(self);
3343        if let Some((excerpt_id, buffer_id, buffer)) = self.as_singleton() {
3344            return Anchor {
3345                buffer_id: Some(buffer_id),
3346                excerpt_id: *excerpt_id,
3347                text_anchor: buffer.anchor_at(offset, bias),
3348            };
3349        }
3350
3351        let mut cursor = self.excerpts.cursor::<(usize, Option<ExcerptId>)>(&());
3352        cursor.seek(&offset, Bias::Right, &());
3353        if cursor.item().is_none() && offset == cursor.start().0 && bias == Bias::Left {
3354            cursor.prev(&());
3355        }
3356        if let Some(excerpt) = cursor.item() {
3357            let mut overshoot = offset.saturating_sub(cursor.start().0);
3358            if excerpt.has_trailing_newline && offset == cursor.end(&()).0 {
3359                overshoot -= 1;
3360                bias = Bias::Right;
3361            }
3362
3363            let buffer_start = excerpt.range.context.start.to_offset(&excerpt.buffer);
3364            let text_anchor =
3365                excerpt.clip_anchor(excerpt.buffer.anchor_at(buffer_start + overshoot, bias));
3366            Anchor {
3367                buffer_id: Some(excerpt.buffer_id),
3368                excerpt_id: excerpt.id,
3369                text_anchor,
3370            }
3371        } else if offset == 0 && bias == Bias::Left {
3372            Anchor::min()
3373        } else {
3374            Anchor::max()
3375        }
3376    }
3377
3378    /// Returns an anchor for the given excerpt and text anchor,
3379    /// returns None if the excerpt_id is no longer valid.
3380    pub fn anchor_in_excerpt(
3381        &self,
3382        excerpt_id: ExcerptId,
3383        text_anchor: text::Anchor,
3384    ) -> Option<Anchor> {
3385        let locator = self.excerpt_locator_for_id(excerpt_id);
3386        let mut cursor = self.excerpts.cursor::<Option<&Locator>>(&());
3387        cursor.seek(locator, Bias::Left, &());
3388        if let Some(excerpt) = cursor.item() {
3389            if excerpt.id == excerpt_id {
3390                let text_anchor = excerpt.clip_anchor(text_anchor);
3391                drop(cursor);
3392                return Some(Anchor {
3393                    buffer_id: Some(excerpt.buffer_id),
3394                    excerpt_id,
3395                    text_anchor,
3396                });
3397            }
3398        }
3399        None
3400    }
3401
3402    pub fn context_range_for_excerpt(&self, excerpt_id: ExcerptId) -> Option<Range<text::Anchor>> {
3403        Some(self.excerpt(excerpt_id)?.range.context.clone())
3404    }
3405
3406    pub fn can_resolve(&self, anchor: &Anchor) -> bool {
3407        if anchor.excerpt_id == ExcerptId::min() || anchor.excerpt_id == ExcerptId::max() {
3408            true
3409        } else if let Some(excerpt) = self.excerpt(anchor.excerpt_id) {
3410            excerpt.buffer.can_resolve(&anchor.text_anchor)
3411        } else {
3412            false
3413        }
3414    }
3415
3416    pub fn excerpts(
3417        &self,
3418    ) -> impl Iterator<Item = (ExcerptId, &BufferSnapshot, ExcerptRange<text::Anchor>)> {
3419        self.excerpts
3420            .iter()
3421            .map(|excerpt| (excerpt.id, &excerpt.buffer, excerpt.range.clone()))
3422    }
3423
3424    fn excerpts_for_range<T: ToOffset>(
3425        &self,
3426        range: Range<T>,
3427    ) -> impl Iterator<Item = (&Excerpt, usize)> + '_ {
3428        let range = range.start.to_offset(self)..range.end.to_offset(self);
3429
3430        let mut cursor = self.excerpts.cursor::<usize>(&());
3431        cursor.seek(&range.start, Bias::Right, &());
3432        cursor.prev(&());
3433
3434        iter::from_fn(move || {
3435            cursor.next(&());
3436            if cursor.start() < &range.end {
3437                cursor.item().map(|item| (item, *cursor.start()))
3438            } else {
3439                None
3440            }
3441        })
3442    }
3443
3444    pub fn excerpt_boundaries_in_range<R, T>(
3445        &self,
3446        range: R,
3447    ) -> impl Iterator<Item = ExcerptBoundary> + '_
3448    where
3449        R: RangeBounds<T>,
3450        T: ToOffset,
3451    {
3452        let start_offset;
3453        let start = match range.start_bound() {
3454            Bound::Included(start) => {
3455                start_offset = start.to_offset(self);
3456                Bound::Included(start_offset)
3457            }
3458            Bound::Excluded(start) => {
3459                start_offset = start.to_offset(self);
3460                Bound::Excluded(start_offset)
3461            }
3462            Bound::Unbounded => {
3463                start_offset = 0;
3464                Bound::Unbounded
3465            }
3466        };
3467        let end = match range.end_bound() {
3468            Bound::Included(end) => Bound::Included(end.to_offset(self)),
3469            Bound::Excluded(end) => Bound::Excluded(end.to_offset(self)),
3470            Bound::Unbounded => Bound::Unbounded,
3471        };
3472        let bounds = (start, end);
3473
3474        let mut cursor = self.excerpts.cursor::<(usize, Point)>(&());
3475        cursor.seek(&start_offset, Bias::Right, &());
3476        if cursor.item().is_none() {
3477            cursor.prev(&());
3478        }
3479        if !bounds.contains(&cursor.start().0) {
3480            cursor.next(&());
3481        }
3482
3483        let mut visited_end = false;
3484        std::iter::from_fn(move || {
3485            if self.singleton {
3486                None
3487            } else if bounds.contains(&cursor.start().0) {
3488                let next = cursor.item().map(|excerpt| ExcerptInfo {
3489                    id: excerpt.id,
3490                    buffer: excerpt.buffer.clone(),
3491                    buffer_id: excerpt.buffer_id,
3492                    range: excerpt.range.clone(),
3493                });
3494
3495                if next.is_none() {
3496                    if visited_end {
3497                        return None;
3498                    } else {
3499                        visited_end = true;
3500                    }
3501                }
3502
3503                let prev = cursor.prev_item().map(|prev_excerpt| ExcerptInfo {
3504                    id: prev_excerpt.id,
3505                    buffer: prev_excerpt.buffer.clone(),
3506                    buffer_id: prev_excerpt.buffer_id,
3507                    range: prev_excerpt.range.clone(),
3508                });
3509                let row = MultiBufferRow(cursor.start().1.row);
3510
3511                cursor.next(&());
3512
3513                Some(ExcerptBoundary { row, prev, next })
3514            } else {
3515                None
3516            }
3517        })
3518    }
3519
3520    pub fn edit_count(&self) -> usize {
3521        self.edit_count
3522    }
3523
3524    pub fn non_text_state_update_count(&self) -> usize {
3525        self.non_text_state_update_count
3526    }
3527
3528    /// Returns the smallest enclosing bracket ranges containing the given range or
3529    /// None if no brackets contain range or the range is not contained in a single
3530    /// excerpt
3531    ///
3532    /// Can optionally pass a range_filter to filter the ranges of brackets to consider
3533    pub fn innermost_enclosing_bracket_ranges<T: ToOffset>(
3534        &self,
3535        range: Range<T>,
3536        range_filter: Option<&dyn Fn(Range<usize>, Range<usize>) -> bool>,
3537    ) -> Option<(Range<usize>, Range<usize>)> {
3538        let range = range.start.to_offset(self)..range.end.to_offset(self);
3539        let excerpt = self.excerpt_containing(range.clone())?;
3540
3541        // Filter to ranges contained in the excerpt
3542        let range_filter = |open: Range<usize>, close: Range<usize>| -> bool {
3543            excerpt.contains_buffer_range(open.start..close.end)
3544                && range_filter.map_or(true, |filter| {
3545                    filter(
3546                        excerpt.map_range_from_buffer(open),
3547                        excerpt.map_range_from_buffer(close),
3548                    )
3549                })
3550        };
3551
3552        let (open, close) = excerpt.buffer().innermost_enclosing_bracket_ranges(
3553            excerpt.map_range_to_buffer(range),
3554            Some(&range_filter),
3555        )?;
3556
3557        Some((
3558            excerpt.map_range_from_buffer(open),
3559            excerpt.map_range_from_buffer(close),
3560        ))
3561    }
3562
3563    /// Returns enclosing bracket ranges containing the given range or returns None if the range is
3564    /// not contained in a single excerpt
3565    pub fn enclosing_bracket_ranges<T: ToOffset>(
3566        &self,
3567        range: Range<T>,
3568    ) -> Option<impl Iterator<Item = (Range<usize>, Range<usize>)> + '_> {
3569        let range = range.start.to_offset(self)..range.end.to_offset(self);
3570        let excerpt = self.excerpt_containing(range.clone())?;
3571
3572        Some(
3573            excerpt
3574                .buffer()
3575                .enclosing_bracket_ranges(excerpt.map_range_to_buffer(range))
3576                .filter_map(move |(open, close)| {
3577                    if excerpt.contains_buffer_range(open.start..close.end) {
3578                        Some((
3579                            excerpt.map_range_from_buffer(open),
3580                            excerpt.map_range_from_buffer(close),
3581                        ))
3582                    } else {
3583                        None
3584                    }
3585                }),
3586        )
3587    }
3588
3589    /// Returns bracket range pairs overlapping the given `range` or returns None if the `range` is
3590    /// not contained in a single excerpt
3591    pub fn bracket_ranges<T: ToOffset>(
3592        &self,
3593        range: Range<T>,
3594    ) -> Option<impl Iterator<Item = (Range<usize>, Range<usize>)> + '_> {
3595        let range = range.start.to_offset(self)..range.end.to_offset(self);
3596        let excerpt = self.excerpt_containing(range.clone())?;
3597
3598        Some(
3599            excerpt
3600                .buffer()
3601                .bracket_ranges(excerpt.map_range_to_buffer(range))
3602                .filter_map(move |(start_bracket_range, close_bracket_range)| {
3603                    let buffer_range = start_bracket_range.start..close_bracket_range.end;
3604                    if excerpt.contains_buffer_range(buffer_range) {
3605                        Some((
3606                            excerpt.map_range_from_buffer(start_bracket_range),
3607                            excerpt.map_range_from_buffer(close_bracket_range),
3608                        ))
3609                    } else {
3610                        None
3611                    }
3612                }),
3613        )
3614    }
3615
3616    pub fn redacted_ranges<'a, T: ToOffset>(
3617        &'a self,
3618        range: Range<T>,
3619        redaction_enabled: impl Fn(Option<&Arc<dyn File>>) -> bool + 'a,
3620    ) -> impl Iterator<Item = Range<usize>> + 'a {
3621        let range = range.start.to_offset(self)..range.end.to_offset(self);
3622        self.excerpts_for_range(range.clone())
3623            .filter(move |&(excerpt, _)| redaction_enabled(excerpt.buffer.file()))
3624            .flat_map(move |(excerpt, excerpt_offset)| {
3625                let excerpt_buffer_start = excerpt.range.context.start.to_offset(&excerpt.buffer);
3626
3627                excerpt
3628                    .buffer
3629                    .redacted_ranges(excerpt.range.context.clone())
3630                    .map(move |mut redacted_range| {
3631                        // Re-base onto the excerpts coordinates in the multibuffer
3632                        redacted_range.start = excerpt_offset
3633                            + redacted_range.start.saturating_sub(excerpt_buffer_start);
3634                        redacted_range.end = excerpt_offset
3635                            + redacted_range.end.saturating_sub(excerpt_buffer_start);
3636
3637                        redacted_range
3638                    })
3639                    .skip_while(move |redacted_range| redacted_range.end < range.start)
3640                    .take_while(move |redacted_range| redacted_range.start < range.end)
3641            })
3642    }
3643
3644    pub fn runnable_ranges(
3645        &self,
3646        range: Range<Anchor>,
3647    ) -> impl Iterator<Item = language::RunnableRange> + '_ {
3648        let range = range.start.to_offset(self)..range.end.to_offset(self);
3649        self.excerpts_for_range(range.clone())
3650            .flat_map(move |(excerpt, excerpt_offset)| {
3651                let excerpt_buffer_start = excerpt.range.context.start.to_offset(&excerpt.buffer);
3652
3653                excerpt
3654                    .buffer
3655                    .runnable_ranges(excerpt.range.context.clone())
3656                    .filter_map(move |mut runnable| {
3657                        // Re-base onto the excerpts coordinates in the multibuffer
3658                        //
3659                        // The node matching our runnables query might partially overlap with
3660                        // the provided range. If the run indicator is outside of excerpt bounds, do not actually show it.
3661                        if runnable.run_range.start < excerpt_buffer_start {
3662                            return None;
3663                        }
3664                        if language::ToPoint::to_point(&runnable.run_range.end, &excerpt.buffer).row
3665                            > excerpt.max_buffer_row
3666                        {
3667                            return None;
3668                        }
3669                        runnable.run_range.start =
3670                            excerpt_offset + runnable.run_range.start - excerpt_buffer_start;
3671                        runnable.run_range.end =
3672                            excerpt_offset + runnable.run_range.end - excerpt_buffer_start;
3673                        Some(runnable)
3674                    })
3675                    .skip_while(move |runnable| runnable.run_range.end < range.start)
3676                    .take_while(move |runnable| runnable.run_range.start < range.end)
3677            })
3678    }
3679
3680    pub fn indent_guides_in_range(
3681        &self,
3682        range: Range<Anchor>,
3683        ignore_disabled_for_language: bool,
3684        cx: &AppContext,
3685    ) -> Vec<MultiBufferIndentGuide> {
3686        // Fast path for singleton buffers, we can skip the conversion between offsets.
3687        if let Some((_, _, snapshot)) = self.as_singleton() {
3688            return snapshot
3689                .indent_guides_in_range(
3690                    range.start.text_anchor..range.end.text_anchor,
3691                    ignore_disabled_for_language,
3692                    cx,
3693                )
3694                .into_iter()
3695                .map(|guide| MultiBufferIndentGuide {
3696                    multibuffer_row_range: MultiBufferRow(guide.start_row)
3697                        ..MultiBufferRow(guide.end_row),
3698                    buffer: guide,
3699                })
3700                .collect();
3701        }
3702
3703        let range = range.start.to_offset(self)..range.end.to_offset(self);
3704
3705        self.excerpts_for_range(range.clone())
3706            .flat_map(move |(excerpt, excerpt_offset)| {
3707                let excerpt_buffer_start_row =
3708                    excerpt.range.context.start.to_point(&excerpt.buffer).row;
3709                let excerpt_offset_row = crate::ToPoint::to_point(&excerpt_offset, self).row;
3710
3711                excerpt
3712                    .buffer
3713                    .indent_guides_in_range(
3714                        excerpt.range.context.clone(),
3715                        ignore_disabled_for_language,
3716                        cx,
3717                    )
3718                    .into_iter()
3719                    .map(move |indent_guide| {
3720                        let start_row = excerpt_offset_row
3721                            + (indent_guide.start_row - excerpt_buffer_start_row);
3722                        let end_row =
3723                            excerpt_offset_row + (indent_guide.end_row - excerpt_buffer_start_row);
3724
3725                        MultiBufferIndentGuide {
3726                            multibuffer_row_range: MultiBufferRow(start_row)
3727                                ..MultiBufferRow(end_row),
3728                            buffer: indent_guide,
3729                        }
3730                    })
3731            })
3732            .collect()
3733    }
3734
3735    pub fn trailing_excerpt_update_count(&self) -> usize {
3736        self.trailing_excerpt_update_count
3737    }
3738
3739    pub fn file_at<T: ToOffset>(&self, point: T) -> Option<&Arc<dyn File>> {
3740        self.point_to_buffer_offset(point)
3741            .and_then(|(buffer, _)| buffer.file())
3742    }
3743
3744    pub fn language_at<T: ToOffset>(&self, point: T) -> Option<&Arc<Language>> {
3745        self.point_to_buffer_offset(point)
3746            .and_then(|(buffer, offset)| buffer.language_at(offset))
3747    }
3748
3749    pub fn settings_at<'a, T: ToOffset>(
3750        &'a self,
3751        point: T,
3752        cx: &'a AppContext,
3753    ) -> Cow<'a, LanguageSettings> {
3754        let mut language = None;
3755        let mut file = None;
3756        if let Some((buffer, offset)) = self.point_to_buffer_offset(point) {
3757            language = buffer.language_at(offset);
3758            file = buffer.file();
3759        }
3760        language_settings(language.map(|l| l.name()), file, cx)
3761    }
3762
3763    pub fn language_scope_at<T: ToOffset>(&self, point: T) -> Option<LanguageScope> {
3764        self.point_to_buffer_offset(point)
3765            .and_then(|(buffer, offset)| buffer.language_scope_at(offset))
3766    }
3767
3768    pub fn char_classifier_at<T: ToOffset>(&self, point: T) -> CharClassifier {
3769        self.point_to_buffer_offset(point)
3770            .map(|(buffer, offset)| buffer.char_classifier_at(offset))
3771            .unwrap_or_default()
3772    }
3773
3774    pub fn language_indent_size_at<T: ToOffset>(
3775        &self,
3776        position: T,
3777        cx: &AppContext,
3778    ) -> Option<IndentSize> {
3779        let (buffer_snapshot, offset) = self.point_to_buffer_offset(position)?;
3780        Some(buffer_snapshot.language_indent_size_at(offset, cx))
3781    }
3782
3783    pub fn is_dirty(&self) -> bool {
3784        self.is_dirty
3785    }
3786
3787    pub fn has_deleted_file(&self) -> bool {
3788        self.has_deleted_file
3789    }
3790
3791    pub fn has_conflict(&self) -> bool {
3792        self.has_conflict
3793    }
3794
3795    pub fn has_diagnostics(&self) -> bool {
3796        self.excerpts
3797            .iter()
3798            .any(|excerpt| excerpt.buffer.has_diagnostics())
3799    }
3800
3801    pub fn diagnostic_group<'a, O>(
3802        &'a self,
3803        group_id: usize,
3804    ) -> impl Iterator<Item = DiagnosticEntry<O>> + 'a
3805    where
3806        O: text::FromAnchor + 'a,
3807    {
3808        self.as_singleton()
3809            .into_iter()
3810            .flat_map(move |(_, _, buffer)| buffer.diagnostic_group(group_id))
3811    }
3812
3813    pub fn diagnostics_in_range<'a, T, O>(
3814        &'a self,
3815        range: Range<T>,
3816        reversed: bool,
3817    ) -> impl Iterator<Item = DiagnosticEntry<O>> + 'a
3818    where
3819        T: 'a + ToOffset,
3820        O: 'a + text::FromAnchor + Ord,
3821    {
3822        self.as_singleton()
3823            .into_iter()
3824            .flat_map(move |(_, _, buffer)| {
3825                buffer.diagnostics_in_range(
3826                    range.start.to_offset(self)..range.end.to_offset(self),
3827                    reversed,
3828                )
3829            })
3830    }
3831
3832    pub fn has_git_diffs(&self) -> bool {
3833        for excerpt in self.excerpts.iter() {
3834            if excerpt.buffer.has_git_diff() {
3835                return true;
3836            }
3837        }
3838        false
3839    }
3840
3841    pub fn git_diff_hunks_in_range_rev(
3842        &self,
3843        row_range: Range<MultiBufferRow>,
3844    ) -> impl Iterator<Item = MultiBufferDiffHunk> + '_ {
3845        let mut cursor = self.excerpts.cursor::<Point>(&());
3846
3847        cursor.seek(&Point::new(row_range.end.0, 0), Bias::Left, &());
3848        if cursor.item().is_none() {
3849            cursor.prev(&());
3850        }
3851
3852        std::iter::from_fn(move || {
3853            let excerpt = cursor.item()?;
3854            let multibuffer_start = *cursor.start();
3855            let multibuffer_end = multibuffer_start + excerpt.text_summary.lines;
3856            if multibuffer_start.row >= row_range.end.0 {
3857                return None;
3858            }
3859
3860            let mut buffer_start = excerpt.range.context.start;
3861            let mut buffer_end = excerpt.range.context.end;
3862            let excerpt_start_point = buffer_start.to_point(&excerpt.buffer);
3863            let excerpt_end_point = excerpt_start_point + excerpt.text_summary.lines;
3864
3865            if row_range.start.0 > multibuffer_start.row {
3866                let buffer_start_point =
3867                    excerpt_start_point + Point::new(row_range.start.0 - multibuffer_start.row, 0);
3868                buffer_start = excerpt.buffer.anchor_before(buffer_start_point);
3869            }
3870
3871            if row_range.end.0 < multibuffer_end.row {
3872                let buffer_end_point =
3873                    excerpt_start_point + Point::new(row_range.end.0 - multibuffer_start.row, 0);
3874                buffer_end = excerpt.buffer.anchor_before(buffer_end_point);
3875            }
3876
3877            let buffer_hunks = excerpt
3878                .buffer
3879                .git_diff_hunks_intersecting_range_rev(buffer_start..buffer_end)
3880                .map(move |hunk| {
3881                    let start = multibuffer_start.row
3882                        + hunk.row_range.start.saturating_sub(excerpt_start_point.row);
3883                    let end = multibuffer_start.row
3884                        + hunk
3885                            .row_range
3886                            .end
3887                            .min(excerpt_end_point.row + 1)
3888                            .saturating_sub(excerpt_start_point.row);
3889
3890                    MultiBufferDiffHunk {
3891                        row_range: MultiBufferRow(start)..MultiBufferRow(end),
3892                        diff_base_byte_range: hunk.diff_base_byte_range.clone(),
3893                        buffer_range: hunk.buffer_range.clone(),
3894                        buffer_id: excerpt.buffer_id,
3895                    }
3896                });
3897
3898            cursor.prev(&());
3899
3900            Some(buffer_hunks)
3901        })
3902        .flatten()
3903    }
3904
3905    pub fn git_diff_hunks_in_range(
3906        &self,
3907        row_range: Range<MultiBufferRow>,
3908    ) -> impl Iterator<Item = MultiBufferDiffHunk> + '_ {
3909        let mut cursor = self.excerpts.cursor::<Point>(&());
3910
3911        cursor.seek(&Point::new(row_range.start.0, 0), Bias::Left, &());
3912
3913        std::iter::from_fn(move || {
3914            let excerpt = cursor.item()?;
3915            let multibuffer_start = *cursor.start();
3916            let multibuffer_end = multibuffer_start + excerpt.text_summary.lines;
3917            let mut buffer_start = excerpt.range.context.start;
3918            let mut buffer_end = excerpt.range.context.end;
3919
3920            let excerpt_rows = match multibuffer_start.row.cmp(&row_range.end.0) {
3921                cmp::Ordering::Less => {
3922                    let excerpt_start_point = buffer_start.to_point(&excerpt.buffer);
3923                    let excerpt_end_point = excerpt_start_point + excerpt.text_summary.lines;
3924
3925                    if row_range.start.0 > multibuffer_start.row {
3926                        let buffer_start_point = excerpt_start_point
3927                            + Point::new(row_range.start.0 - multibuffer_start.row, 0);
3928                        buffer_start = excerpt.buffer.anchor_before(buffer_start_point);
3929                    }
3930
3931                    if row_range.end.0 < multibuffer_end.row {
3932                        let buffer_end_point = excerpt_start_point
3933                            + Point::new(row_range.end.0 - multibuffer_start.row, 0);
3934                        buffer_end = excerpt.buffer.anchor_before(buffer_end_point);
3935                    }
3936                    excerpt_start_point.row..excerpt_end_point.row
3937                }
3938                cmp::Ordering::Equal if row_range.end.0 == 0 => {
3939                    buffer_end = buffer_start;
3940                    0..0
3941                }
3942                cmp::Ordering::Greater | cmp::Ordering::Equal => return None,
3943            };
3944
3945            let buffer_hunks = excerpt
3946                .buffer
3947                .git_diff_hunks_intersecting_range(buffer_start..buffer_end)
3948                .map(move |hunk| {
3949                    let buffer_range = if excerpt_rows.start == 0 && excerpt_rows.end == 0 {
3950                        MultiBufferRow(0)..MultiBufferRow(1)
3951                    } else {
3952                        let start = multibuffer_start.row
3953                            + hunk.row_range.start.saturating_sub(excerpt_rows.start);
3954                        let end = multibuffer_start.row
3955                            + hunk
3956                                .row_range
3957                                .end
3958                                .min(excerpt_rows.end + 1)
3959                                .saturating_sub(excerpt_rows.start);
3960                        MultiBufferRow(start)..MultiBufferRow(end)
3961                    };
3962                    MultiBufferDiffHunk {
3963                        row_range: buffer_range,
3964                        diff_base_byte_range: hunk.diff_base_byte_range.clone(),
3965                        buffer_range: hunk.buffer_range.clone(),
3966                        buffer_id: excerpt.buffer_id,
3967                    }
3968                });
3969
3970            cursor.next(&());
3971
3972            Some(buffer_hunks)
3973        })
3974        .flatten()
3975    }
3976
3977    pub fn range_for_syntax_ancestor<T: ToOffset>(&self, range: Range<T>) -> Option<Range<usize>> {
3978        let range = range.start.to_offset(self)..range.end.to_offset(self);
3979        let excerpt = self.excerpt_containing(range.clone())?;
3980
3981        let ancestor_buffer_range = excerpt
3982            .buffer()
3983            .range_for_syntax_ancestor(excerpt.map_range_to_buffer(range))?;
3984
3985        Some(excerpt.map_range_from_buffer(ancestor_buffer_range))
3986    }
3987
3988    pub fn outline(&self, theme: Option<&SyntaxTheme>) -> Option<Outline<Anchor>> {
3989        let (excerpt_id, _, buffer) = self.as_singleton()?;
3990        let outline = buffer.outline(theme)?;
3991        Some(Outline::new(
3992            outline
3993                .items
3994                .into_iter()
3995                .flat_map(|item| {
3996                    Some(OutlineItem {
3997                        depth: item.depth,
3998                        range: self.anchor_in_excerpt(*excerpt_id, item.range.start)?
3999                            ..self.anchor_in_excerpt(*excerpt_id, item.range.end)?,
4000                        text: item.text,
4001                        highlight_ranges: item.highlight_ranges,
4002                        name_ranges: item.name_ranges,
4003                        body_range: item.body_range.and_then(|body_range| {
4004                            Some(
4005                                self.anchor_in_excerpt(*excerpt_id, body_range.start)?
4006                                    ..self.anchor_in_excerpt(*excerpt_id, body_range.end)?,
4007                            )
4008                        }),
4009                        annotation_range: item.annotation_range.and_then(|annotation_range| {
4010                            Some(
4011                                self.anchor_in_excerpt(*excerpt_id, annotation_range.start)?
4012                                    ..self.anchor_in_excerpt(*excerpt_id, annotation_range.end)?,
4013                            )
4014                        }),
4015                    })
4016                })
4017                .collect(),
4018        ))
4019    }
4020
4021    pub fn symbols_containing<T: ToOffset>(
4022        &self,
4023        offset: T,
4024        theme: Option<&SyntaxTheme>,
4025    ) -> Option<(BufferId, Vec<OutlineItem<Anchor>>)> {
4026        let anchor = self.anchor_before(offset);
4027        let excerpt_id = anchor.excerpt_id;
4028        let excerpt = self.excerpt(excerpt_id)?;
4029        Some((
4030            excerpt.buffer_id,
4031            excerpt
4032                .buffer
4033                .symbols_containing(anchor.text_anchor, theme)
4034                .into_iter()
4035                .flatten()
4036                .flat_map(|item| {
4037                    Some(OutlineItem {
4038                        depth: item.depth,
4039                        range: self.anchor_in_excerpt(excerpt_id, item.range.start)?
4040                            ..self.anchor_in_excerpt(excerpt_id, item.range.end)?,
4041                        text: item.text,
4042                        highlight_ranges: item.highlight_ranges,
4043                        name_ranges: item.name_ranges,
4044                        body_range: item.body_range.and_then(|body_range| {
4045                            Some(
4046                                self.anchor_in_excerpt(excerpt_id, body_range.start)?
4047                                    ..self.anchor_in_excerpt(excerpt_id, body_range.end)?,
4048                            )
4049                        }),
4050                        annotation_range: item.annotation_range.and_then(|body_range| {
4051                            Some(
4052                                self.anchor_in_excerpt(excerpt_id, body_range.start)?
4053                                    ..self.anchor_in_excerpt(excerpt_id, body_range.end)?,
4054                            )
4055                        }),
4056                    })
4057                })
4058                .collect(),
4059        ))
4060    }
4061
4062    fn excerpt_locator_for_id(&self, id: ExcerptId) -> &Locator {
4063        if id == ExcerptId::min() {
4064            Locator::min_ref()
4065        } else if id == ExcerptId::max() {
4066            Locator::max_ref()
4067        } else {
4068            let mut cursor = self.excerpt_ids.cursor::<ExcerptId>(&());
4069            cursor.seek(&id, Bias::Left, &());
4070            if let Some(entry) = cursor.item() {
4071                if entry.id == id {
4072                    return &entry.locator;
4073                }
4074            }
4075            panic!("invalid excerpt id {:?}", id)
4076        }
4077    }
4078
4079    /// Returns the locators referenced by the given excerpt IDs, sorted by locator.
4080    fn excerpt_locators_for_ids(
4081        &self,
4082        ids: impl IntoIterator<Item = ExcerptId>,
4083    ) -> SmallVec<[Locator; 1]> {
4084        let mut sorted_ids = ids.into_iter().collect::<SmallVec<[_; 1]>>();
4085        sorted_ids.sort_unstable();
4086        let mut locators = SmallVec::new();
4087
4088        while sorted_ids.last() == Some(&ExcerptId::max()) {
4089            sorted_ids.pop();
4090            if let Some(mapping) = self.excerpt_ids.last() {
4091                locators.push(mapping.locator.clone());
4092            }
4093        }
4094
4095        let mut sorted_ids = sorted_ids.into_iter().dedup().peekable();
4096        if sorted_ids.peek() == Some(&ExcerptId::min()) {
4097            sorted_ids.next();
4098            if let Some(mapping) = self.excerpt_ids.first() {
4099                locators.push(mapping.locator.clone());
4100            }
4101        }
4102
4103        let mut cursor = self.excerpt_ids.cursor::<ExcerptId>(&());
4104        for id in sorted_ids {
4105            if cursor.seek_forward(&id, Bias::Left, &()) {
4106                locators.push(cursor.item().unwrap().locator.clone());
4107            } else {
4108                panic!("invalid excerpt id {:?}", id);
4109            }
4110        }
4111
4112        locators.sort_unstable();
4113        locators
4114    }
4115
4116    pub fn buffer_id_for_excerpt(&self, excerpt_id: ExcerptId) -> Option<BufferId> {
4117        Some(self.excerpt(excerpt_id)?.buffer_id)
4118    }
4119
4120    pub fn buffer_for_excerpt(&self, excerpt_id: ExcerptId) -> Option<&BufferSnapshot> {
4121        Some(&self.excerpt(excerpt_id)?.buffer)
4122    }
4123
4124    pub fn range_for_excerpt<'a, T: sum_tree::Dimension<'a, ExcerptSummary>>(
4125        &'a self,
4126        excerpt_id: ExcerptId,
4127    ) -> Option<Range<T>> {
4128        let mut cursor = self.excerpts.cursor::<(Option<&Locator>, T)>(&());
4129        let locator = self.excerpt_locator_for_id(excerpt_id);
4130        if cursor.seek(&Some(locator), Bias::Left, &()) {
4131            let start = cursor.start().1.clone();
4132            let end = cursor.end(&()).1;
4133            Some(start..end)
4134        } else {
4135            None
4136        }
4137    }
4138
4139    fn excerpt(&self, excerpt_id: ExcerptId) -> Option<&Excerpt> {
4140        let mut cursor = self.excerpts.cursor::<Option<&Locator>>(&());
4141        let locator = self.excerpt_locator_for_id(excerpt_id);
4142        cursor.seek(&Some(locator), Bias::Left, &());
4143        if let Some(excerpt) = cursor.item() {
4144            if excerpt.id == excerpt_id {
4145                return Some(excerpt);
4146            }
4147        }
4148        None
4149    }
4150
4151    /// Returns the excerpt containing range and its offset start within the multibuffer or none if `range` spans multiple excerpts
4152    pub fn excerpt_containing<T: ToOffset>(&self, range: Range<T>) -> Option<MultiBufferExcerpt> {
4153        let range = range.start.to_offset(self)..range.end.to_offset(self);
4154
4155        let mut cursor = self.excerpts.cursor::<usize>(&());
4156        cursor.seek(&range.start, Bias::Right, &());
4157        let start_excerpt = cursor.item()?;
4158
4159        if range.start == range.end {
4160            return Some(MultiBufferExcerpt::new(start_excerpt, *cursor.start()));
4161        }
4162
4163        cursor.seek(&range.end, Bias::Right, &());
4164        let end_excerpt = cursor.item()?;
4165
4166        if start_excerpt.id == end_excerpt.id {
4167            Some(MultiBufferExcerpt::new(start_excerpt, *cursor.start()))
4168        } else {
4169            None
4170        }
4171    }
4172
4173    // Takes an iterator over anchor ranges and returns a new iterator over anchor ranges that don't
4174    // span across excerpt boundaries.
4175    pub fn split_ranges<'a, I>(&'a self, ranges: I) -> impl Iterator<Item = Range<Anchor>> + 'a
4176    where
4177        I: IntoIterator<Item = Range<Anchor>> + 'a,
4178    {
4179        let mut ranges = ranges.into_iter().map(|range| range.to_offset(self));
4180        let mut cursor = self.excerpts.cursor::<usize>(&());
4181        cursor.next(&());
4182        let mut current_range = ranges.next();
4183        iter::from_fn(move || {
4184            let range = current_range.clone()?;
4185            if range.start >= cursor.end(&()) {
4186                cursor.seek_forward(&range.start, Bias::Right, &());
4187                if range.start == self.len() {
4188                    cursor.prev(&());
4189                }
4190            }
4191
4192            let excerpt = cursor.item()?;
4193            let range_start_in_excerpt = cmp::max(range.start, *cursor.start());
4194            let range_end_in_excerpt = if excerpt.has_trailing_newline {
4195                cmp::min(range.end, cursor.end(&()) - 1)
4196            } else {
4197                cmp::min(range.end, cursor.end(&()))
4198            };
4199            let buffer_range = MultiBufferExcerpt::new(excerpt, *cursor.start())
4200                .map_range_to_buffer(range_start_in_excerpt..range_end_in_excerpt);
4201
4202            let subrange_start_anchor = Anchor {
4203                buffer_id: Some(excerpt.buffer_id),
4204                excerpt_id: excerpt.id,
4205                text_anchor: excerpt.buffer.anchor_before(buffer_range.start),
4206            };
4207            let subrange_end_anchor = Anchor {
4208                buffer_id: Some(excerpt.buffer_id),
4209                excerpt_id: excerpt.id,
4210                text_anchor: excerpt.buffer.anchor_after(buffer_range.end),
4211            };
4212
4213            if range.end > cursor.end(&()) {
4214                cursor.next(&());
4215            } else {
4216                current_range = ranges.next();
4217            }
4218
4219            Some(subrange_start_anchor..subrange_end_anchor)
4220        })
4221    }
4222
4223    /// Returns excerpts overlapping the given ranges. If range spans multiple excerpts returns one range for each excerpt
4224    ///
4225    /// The ranges are specified in the coordinate space of the multibuffer, not the individual excerpted buffers.
4226    /// Each returned excerpt's range is in the coordinate space of its source buffer.
4227    pub fn excerpts_in_ranges(
4228        &self,
4229        ranges: impl IntoIterator<Item = Range<Anchor>>,
4230    ) -> impl Iterator<Item = (ExcerptId, &BufferSnapshot, Range<usize>)> {
4231        let mut ranges = ranges.into_iter().map(|range| range.to_offset(self));
4232        let mut cursor = self.excerpts.cursor::<usize>(&());
4233        cursor.next(&());
4234        let mut current_range = ranges.next();
4235        iter::from_fn(move || {
4236            let range = current_range.clone()?;
4237            if range.start >= cursor.end(&()) {
4238                cursor.seek_forward(&range.start, Bias::Right, &());
4239                if range.start == self.len() {
4240                    cursor.prev(&());
4241                }
4242            }
4243
4244            let excerpt = cursor.item()?;
4245            let range_start_in_excerpt = cmp::max(range.start, *cursor.start());
4246            let range_end_in_excerpt = if excerpt.has_trailing_newline {
4247                cmp::min(range.end, cursor.end(&()) - 1)
4248            } else {
4249                cmp::min(range.end, cursor.end(&()))
4250            };
4251            let buffer_range = MultiBufferExcerpt::new(excerpt, *cursor.start())
4252                .map_range_to_buffer(range_start_in_excerpt..range_end_in_excerpt);
4253
4254            if range.end > cursor.end(&()) {
4255                cursor.next(&());
4256            } else {
4257                current_range = ranges.next();
4258            }
4259
4260            Some((excerpt.id, &excerpt.buffer, buffer_range))
4261        })
4262    }
4263
4264    pub fn selections_in_range<'a>(
4265        &'a self,
4266        range: &'a Range<Anchor>,
4267        include_local: bool,
4268    ) -> impl 'a + Iterator<Item = (ReplicaId, bool, CursorShape, Selection<Anchor>)> {
4269        let mut cursor = self.excerpts.cursor::<ExcerptSummary>(&());
4270        let start_locator = self.excerpt_locator_for_id(range.start.excerpt_id);
4271        let end_locator = self.excerpt_locator_for_id(range.end.excerpt_id);
4272        cursor.seek(start_locator, Bias::Left, &());
4273        cursor
4274            .take_while(move |excerpt| excerpt.locator <= *end_locator)
4275            .flat_map(move |excerpt| {
4276                let mut query_range = excerpt.range.context.start..excerpt.range.context.end;
4277                if excerpt.id == range.start.excerpt_id {
4278                    query_range.start = range.start.text_anchor;
4279                }
4280                if excerpt.id == range.end.excerpt_id {
4281                    query_range.end = range.end.text_anchor;
4282                }
4283
4284                excerpt
4285                    .buffer
4286                    .selections_in_range(query_range, include_local)
4287                    .flat_map(move |(replica_id, line_mode, cursor_shape, selections)| {
4288                        selections.map(move |selection| {
4289                            let mut start = Anchor {
4290                                buffer_id: Some(excerpt.buffer_id),
4291                                excerpt_id: excerpt.id,
4292                                text_anchor: selection.start,
4293                            };
4294                            let mut end = Anchor {
4295                                buffer_id: Some(excerpt.buffer_id),
4296                                excerpt_id: excerpt.id,
4297                                text_anchor: selection.end,
4298                            };
4299                            if range.start.cmp(&start, self).is_gt() {
4300                                start = range.start;
4301                            }
4302                            if range.end.cmp(&end, self).is_lt() {
4303                                end = range.end;
4304                            }
4305
4306                            (
4307                                replica_id,
4308                                line_mode,
4309                                cursor_shape,
4310                                Selection {
4311                                    id: selection.id,
4312                                    start,
4313                                    end,
4314                                    reversed: selection.reversed,
4315                                    goal: selection.goal,
4316                                },
4317                            )
4318                        })
4319                    })
4320            })
4321    }
4322
4323    pub fn show_headers(&self) -> bool {
4324        self.show_headers
4325    }
4326}
4327
4328#[cfg(any(test, feature = "test-support"))]
4329impl MultiBufferSnapshot {
4330    pub fn random_byte_range(&self, start_offset: usize, rng: &mut impl rand::Rng) -> Range<usize> {
4331        let end = self.clip_offset(rng.gen_range(start_offset..=self.len()), Bias::Right);
4332        let start = self.clip_offset(rng.gen_range(start_offset..=end), Bias::Right);
4333        start..end
4334    }
4335}
4336
4337impl History {
4338    fn start_transaction(&mut self, now: Instant) -> Option<TransactionId> {
4339        self.transaction_depth += 1;
4340        if self.transaction_depth == 1 {
4341            let id = self.next_transaction_id.tick();
4342            self.undo_stack.push(Transaction {
4343                id,
4344                buffer_transactions: Default::default(),
4345                first_edit_at: now,
4346                last_edit_at: now,
4347                suppress_grouping: false,
4348            });
4349            Some(id)
4350        } else {
4351            None
4352        }
4353    }
4354
4355    fn end_transaction(
4356        &mut self,
4357        now: Instant,
4358        buffer_transactions: HashMap<BufferId, TransactionId>,
4359    ) -> bool {
4360        assert_ne!(self.transaction_depth, 0);
4361        self.transaction_depth -= 1;
4362        if self.transaction_depth == 0 {
4363            if buffer_transactions.is_empty() {
4364                self.undo_stack.pop();
4365                false
4366            } else {
4367                self.redo_stack.clear();
4368                let transaction = self.undo_stack.last_mut().unwrap();
4369                transaction.last_edit_at = now;
4370                for (buffer_id, transaction_id) in buffer_transactions {
4371                    transaction
4372                        .buffer_transactions
4373                        .entry(buffer_id)
4374                        .or_insert(transaction_id);
4375                }
4376                true
4377            }
4378        } else {
4379            false
4380        }
4381    }
4382
4383    fn push_transaction<'a, T>(
4384        &mut self,
4385        buffer_transactions: T,
4386        now: Instant,
4387        cx: &ModelContext<MultiBuffer>,
4388    ) where
4389        T: IntoIterator<Item = (&'a Model<Buffer>, &'a language::Transaction)>,
4390    {
4391        assert_eq!(self.transaction_depth, 0);
4392        let transaction = Transaction {
4393            id: self.next_transaction_id.tick(),
4394            buffer_transactions: buffer_transactions
4395                .into_iter()
4396                .map(|(buffer, transaction)| (buffer.read(cx).remote_id(), transaction.id))
4397                .collect(),
4398            first_edit_at: now,
4399            last_edit_at: now,
4400            suppress_grouping: false,
4401        };
4402        if !transaction.buffer_transactions.is_empty() {
4403            self.undo_stack.push(transaction);
4404            self.redo_stack.clear();
4405        }
4406    }
4407
4408    fn finalize_last_transaction(&mut self) {
4409        if let Some(transaction) = self.undo_stack.last_mut() {
4410            transaction.suppress_grouping = true;
4411        }
4412    }
4413
4414    fn forget(&mut self, transaction_id: TransactionId) -> Option<Transaction> {
4415        if let Some(ix) = self
4416            .undo_stack
4417            .iter()
4418            .rposition(|transaction| transaction.id == transaction_id)
4419        {
4420            Some(self.undo_stack.remove(ix))
4421        } else if let Some(ix) = self
4422            .redo_stack
4423            .iter()
4424            .rposition(|transaction| transaction.id == transaction_id)
4425        {
4426            Some(self.redo_stack.remove(ix))
4427        } else {
4428            None
4429        }
4430    }
4431
4432    fn transaction(&self, transaction_id: TransactionId) -> Option<&Transaction> {
4433        self.undo_stack
4434            .iter()
4435            .find(|transaction| transaction.id == transaction_id)
4436            .or_else(|| {
4437                self.redo_stack
4438                    .iter()
4439                    .find(|transaction| transaction.id == transaction_id)
4440            })
4441    }
4442
4443    fn transaction_mut(&mut self, transaction_id: TransactionId) -> Option<&mut Transaction> {
4444        self.undo_stack
4445            .iter_mut()
4446            .find(|transaction| transaction.id == transaction_id)
4447            .or_else(|| {
4448                self.redo_stack
4449                    .iter_mut()
4450                    .find(|transaction| transaction.id == transaction_id)
4451            })
4452    }
4453
4454    fn pop_undo(&mut self) -> Option<&mut Transaction> {
4455        assert_eq!(self.transaction_depth, 0);
4456        if let Some(transaction) = self.undo_stack.pop() {
4457            self.redo_stack.push(transaction);
4458            self.redo_stack.last_mut()
4459        } else {
4460            None
4461        }
4462    }
4463
4464    fn pop_redo(&mut self) -> Option<&mut Transaction> {
4465        assert_eq!(self.transaction_depth, 0);
4466        if let Some(transaction) = self.redo_stack.pop() {
4467            self.undo_stack.push(transaction);
4468            self.undo_stack.last_mut()
4469        } else {
4470            None
4471        }
4472    }
4473
4474    fn remove_from_undo(&mut self, transaction_id: TransactionId) -> Option<&Transaction> {
4475        let ix = self
4476            .undo_stack
4477            .iter()
4478            .rposition(|transaction| transaction.id == transaction_id)?;
4479        let transaction = self.undo_stack.remove(ix);
4480        self.redo_stack.push(transaction);
4481        self.redo_stack.last()
4482    }
4483
4484    fn group(&mut self) -> Option<TransactionId> {
4485        let mut count = 0;
4486        let mut transactions = self.undo_stack.iter();
4487        if let Some(mut transaction) = transactions.next_back() {
4488            while let Some(prev_transaction) = transactions.next_back() {
4489                if !prev_transaction.suppress_grouping
4490                    && transaction.first_edit_at - prev_transaction.last_edit_at
4491                        <= self.group_interval
4492                {
4493                    transaction = prev_transaction;
4494                    count += 1;
4495                } else {
4496                    break;
4497                }
4498            }
4499        }
4500        self.group_trailing(count)
4501    }
4502
4503    fn group_until(&mut self, transaction_id: TransactionId) {
4504        let mut count = 0;
4505        for transaction in self.undo_stack.iter().rev() {
4506            if transaction.id == transaction_id {
4507                self.group_trailing(count);
4508                break;
4509            } else if transaction.suppress_grouping {
4510                break;
4511            } else {
4512                count += 1;
4513            }
4514        }
4515    }
4516
4517    fn group_trailing(&mut self, n: usize) -> Option<TransactionId> {
4518        let new_len = self.undo_stack.len() - n;
4519        let (transactions_to_keep, transactions_to_merge) = self.undo_stack.split_at_mut(new_len);
4520        if let Some(last_transaction) = transactions_to_keep.last_mut() {
4521            if let Some(transaction) = transactions_to_merge.last() {
4522                last_transaction.last_edit_at = transaction.last_edit_at;
4523            }
4524            for to_merge in transactions_to_merge {
4525                for (buffer_id, transaction_id) in &to_merge.buffer_transactions {
4526                    last_transaction
4527                        .buffer_transactions
4528                        .entry(*buffer_id)
4529                        .or_insert(*transaction_id);
4530                }
4531            }
4532        }
4533
4534        self.undo_stack.truncate(new_len);
4535        self.undo_stack.last().map(|t| t.id)
4536    }
4537}
4538
4539impl Excerpt {
4540    fn new(
4541        id: ExcerptId,
4542        locator: Locator,
4543        buffer_id: BufferId,
4544        buffer: BufferSnapshot,
4545        range: ExcerptRange<text::Anchor>,
4546        has_trailing_newline: bool,
4547    ) -> Self {
4548        Excerpt {
4549            id,
4550            locator,
4551            max_buffer_row: range.context.end.to_point(&buffer).row,
4552            text_summary: buffer
4553                .text_summary_for_range::<TextSummary, _>(range.context.to_offset(&buffer)),
4554            buffer_id,
4555            buffer,
4556            range,
4557            has_trailing_newline,
4558        }
4559    }
4560
4561    fn chunks_in_range(&self, range: Range<usize>, language_aware: bool) -> ExcerptChunks {
4562        let content_start = self.range.context.start.to_offset(&self.buffer);
4563        let chunks_start = content_start + range.start;
4564        let chunks_end = content_start + cmp::min(range.end, self.text_summary.len);
4565
4566        let footer_height = if self.has_trailing_newline
4567            && range.start <= self.text_summary.len
4568            && range.end > self.text_summary.len
4569        {
4570            1
4571        } else {
4572            0
4573        };
4574
4575        let content_chunks = self.buffer.chunks(chunks_start..chunks_end, language_aware);
4576
4577        ExcerptChunks {
4578            excerpt_id: self.id,
4579            content_chunks,
4580            footer_height,
4581        }
4582    }
4583
4584    fn seek_chunks(&self, excerpt_chunks: &mut ExcerptChunks, range: Range<usize>) {
4585        let content_start = self.range.context.start.to_offset(&self.buffer);
4586        let chunks_start = content_start + range.start;
4587        let chunks_end = content_start + cmp::min(range.end, self.text_summary.len);
4588        excerpt_chunks.content_chunks.seek(chunks_start..chunks_end);
4589        excerpt_chunks.footer_height = if self.has_trailing_newline
4590            && range.start <= self.text_summary.len
4591            && range.end > self.text_summary.len
4592        {
4593            1
4594        } else {
4595            0
4596        };
4597    }
4598
4599    fn bytes_in_range(&self, range: Range<usize>) -> ExcerptBytes {
4600        let content_start = self.range.context.start.to_offset(&self.buffer);
4601        let bytes_start = content_start + range.start;
4602        let bytes_end = content_start + cmp::min(range.end, self.text_summary.len);
4603        let footer_height = if self.has_trailing_newline
4604            && range.start <= self.text_summary.len
4605            && range.end > self.text_summary.len
4606        {
4607            1
4608        } else {
4609            0
4610        };
4611        let content_bytes = self.buffer.bytes_in_range(bytes_start..bytes_end);
4612
4613        ExcerptBytes {
4614            content_bytes,
4615            padding_height: footer_height,
4616            reversed: false,
4617        }
4618    }
4619
4620    fn reversed_bytes_in_range(&self, range: Range<usize>) -> ExcerptBytes {
4621        let content_start = self.range.context.start.to_offset(&self.buffer);
4622        let bytes_start = content_start + range.start;
4623        let bytes_end = content_start + cmp::min(range.end, self.text_summary.len);
4624        let footer_height = if self.has_trailing_newline
4625            && range.start <= self.text_summary.len
4626            && range.end > self.text_summary.len
4627        {
4628            1
4629        } else {
4630            0
4631        };
4632        let content_bytes = self.buffer.reversed_bytes_in_range(bytes_start..bytes_end);
4633
4634        ExcerptBytes {
4635            content_bytes,
4636            padding_height: footer_height,
4637            reversed: true,
4638        }
4639    }
4640
4641    fn clip_anchor(&self, text_anchor: text::Anchor) -> text::Anchor {
4642        if text_anchor
4643            .cmp(&self.range.context.start, &self.buffer)
4644            .is_lt()
4645        {
4646            self.range.context.start
4647        } else if text_anchor
4648            .cmp(&self.range.context.end, &self.buffer)
4649            .is_gt()
4650        {
4651            self.range.context.end
4652        } else {
4653            text_anchor
4654        }
4655    }
4656
4657    fn contains(&self, anchor: &Anchor) -> bool {
4658        Some(self.buffer_id) == anchor.buffer_id
4659            && self
4660                .range
4661                .context
4662                .start
4663                .cmp(&anchor.text_anchor, &self.buffer)
4664                .is_le()
4665            && self
4666                .range
4667                .context
4668                .end
4669                .cmp(&anchor.text_anchor, &self.buffer)
4670                .is_ge()
4671    }
4672
4673    /// The [`Excerpt`]'s start offset in its [`Buffer`]
4674    fn buffer_start_offset(&self) -> usize {
4675        self.range.context.start.to_offset(&self.buffer)
4676    }
4677
4678    /// The [`Excerpt`]'s end offset in its [`Buffer`]
4679    fn buffer_end_offset(&self) -> usize {
4680        self.buffer_start_offset() + self.text_summary.len
4681    }
4682}
4683
4684impl<'a> MultiBufferExcerpt<'a> {
4685    fn new(excerpt: &'a Excerpt, excerpt_offset: usize) -> Self {
4686        MultiBufferExcerpt {
4687            excerpt,
4688            excerpt_offset,
4689        }
4690    }
4691
4692    pub fn buffer(&self) -> &'a BufferSnapshot {
4693        &self.excerpt.buffer
4694    }
4695
4696    /// Maps an offset within the [`MultiBuffer`] to an offset within the [`Buffer`]
4697    pub fn map_offset_to_buffer(&self, offset: usize) -> usize {
4698        self.excerpt.buffer_start_offset() + offset.saturating_sub(self.excerpt_offset)
4699    }
4700
4701    /// Maps a range within the [`MultiBuffer`] to a range within the [`Buffer`]
4702    pub fn map_range_to_buffer(&self, range: Range<usize>) -> Range<usize> {
4703        self.map_offset_to_buffer(range.start)..self.map_offset_to_buffer(range.end)
4704    }
4705
4706    /// Map an offset within the [`Buffer`] to an offset within the [`MultiBuffer`]
4707    pub fn map_offset_from_buffer(&self, buffer_offset: usize) -> usize {
4708        let mut buffer_offset_in_excerpt =
4709            buffer_offset.saturating_sub(self.excerpt.buffer_start_offset());
4710        buffer_offset_in_excerpt =
4711            cmp::min(buffer_offset_in_excerpt, self.excerpt.text_summary.len);
4712
4713        self.excerpt_offset + buffer_offset_in_excerpt
4714    }
4715
4716    /// Map a range within the [`Buffer`] to a range within the [`MultiBuffer`]
4717    pub fn map_range_from_buffer(&self, buffer_range: Range<usize>) -> Range<usize> {
4718        self.map_offset_from_buffer(buffer_range.start)
4719            ..self.map_offset_from_buffer(buffer_range.end)
4720    }
4721
4722    /// Returns true if the entirety of the given range is in the buffer's excerpt
4723    pub fn contains_buffer_range(&self, range: Range<usize>) -> bool {
4724        range.start >= self.excerpt.buffer_start_offset()
4725            && range.end <= self.excerpt.buffer_end_offset()
4726    }
4727}
4728
4729impl ExcerptId {
4730    pub fn min() -> Self {
4731        Self(0)
4732    }
4733
4734    pub fn max() -> Self {
4735        Self(usize::MAX)
4736    }
4737
4738    pub fn to_proto(&self) -> u64 {
4739        self.0 as _
4740    }
4741
4742    pub fn from_proto(proto: u64) -> Self {
4743        Self(proto as _)
4744    }
4745
4746    pub fn cmp(&self, other: &Self, snapshot: &MultiBufferSnapshot) -> cmp::Ordering {
4747        let a = snapshot.excerpt_locator_for_id(*self);
4748        let b = snapshot.excerpt_locator_for_id(*other);
4749        a.cmp(b).then_with(|| self.0.cmp(&other.0))
4750    }
4751}
4752
4753impl From<ExcerptId> for usize {
4754    fn from(val: ExcerptId) -> Self {
4755        val.0
4756    }
4757}
4758
4759impl fmt::Debug for Excerpt {
4760    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
4761        f.debug_struct("Excerpt")
4762            .field("id", &self.id)
4763            .field("locator", &self.locator)
4764            .field("buffer_id", &self.buffer_id)
4765            .field("range", &self.range)
4766            .field("text_summary", &self.text_summary)
4767            .field("has_trailing_newline", &self.has_trailing_newline)
4768            .finish()
4769    }
4770}
4771
4772impl sum_tree::Item for Excerpt {
4773    type Summary = ExcerptSummary;
4774
4775    fn summary(&self, _cx: &()) -> Self::Summary {
4776        let mut text = self.text_summary.clone();
4777        if self.has_trailing_newline {
4778            text += TextSummary::from("\n");
4779        }
4780        ExcerptSummary {
4781            excerpt_id: self.id,
4782            excerpt_locator: self.locator.clone(),
4783            max_buffer_row: MultiBufferRow(self.max_buffer_row),
4784            text,
4785        }
4786    }
4787}
4788
4789impl sum_tree::Item for ExcerptIdMapping {
4790    type Summary = ExcerptId;
4791
4792    fn summary(&self, _cx: &()) -> Self::Summary {
4793        self.id
4794    }
4795}
4796
4797impl sum_tree::KeyedItem for ExcerptIdMapping {
4798    type Key = ExcerptId;
4799
4800    fn key(&self) -> Self::Key {
4801        self.id
4802    }
4803}
4804
4805impl sum_tree::Summary for ExcerptId {
4806    type Context = ();
4807
4808    fn zero(_cx: &()) -> Self {
4809        Default::default()
4810    }
4811
4812    fn add_summary(&mut self, other: &Self, _: &()) {
4813        *self = *other;
4814    }
4815}
4816
4817impl sum_tree::Summary for ExcerptSummary {
4818    type Context = ();
4819
4820    fn zero(_cx: &()) -> Self {
4821        Default::default()
4822    }
4823
4824    fn add_summary(&mut self, summary: &Self, _: &()) {
4825        debug_assert!(summary.excerpt_locator > self.excerpt_locator);
4826        self.excerpt_locator = summary.excerpt_locator.clone();
4827        self.text.add_summary(&summary.text, &());
4828        self.max_buffer_row = cmp::max(self.max_buffer_row, summary.max_buffer_row);
4829    }
4830}
4831
4832impl<'a> sum_tree::Dimension<'a, ExcerptSummary> for TextSummary {
4833    fn zero(_cx: &()) -> Self {
4834        Default::default()
4835    }
4836
4837    fn add_summary(&mut self, summary: &'a ExcerptSummary, _: &()) {
4838        *self += &summary.text;
4839    }
4840}
4841
4842impl<'a> sum_tree::Dimension<'a, ExcerptSummary> for usize {
4843    fn zero(_cx: &()) -> Self {
4844        Default::default()
4845    }
4846
4847    fn add_summary(&mut self, summary: &'a ExcerptSummary, _: &()) {
4848        *self += summary.text.len;
4849    }
4850}
4851
4852impl<'a> sum_tree::SeekTarget<'a, ExcerptSummary, ExcerptSummary> for usize {
4853    fn cmp(&self, cursor_location: &ExcerptSummary, _: &()) -> cmp::Ordering {
4854        Ord::cmp(self, &cursor_location.text.len)
4855    }
4856}
4857
4858impl<'a> sum_tree::SeekTarget<'a, ExcerptSummary, TextSummary> for Point {
4859    fn cmp(&self, cursor_location: &TextSummary, _: &()) -> cmp::Ordering {
4860        Ord::cmp(self, &cursor_location.lines)
4861    }
4862}
4863
4864impl<'a> sum_tree::SeekTarget<'a, ExcerptSummary, Option<&'a Locator>> for Locator {
4865    fn cmp(&self, cursor_location: &Option<&'a Locator>, _: &()) -> cmp::Ordering {
4866        Ord::cmp(&Some(self), cursor_location)
4867    }
4868}
4869
4870impl<'a> sum_tree::SeekTarget<'a, ExcerptSummary, ExcerptSummary> for Locator {
4871    fn cmp(&self, cursor_location: &ExcerptSummary, _: &()) -> cmp::Ordering {
4872        Ord::cmp(self, &cursor_location.excerpt_locator)
4873    }
4874}
4875
4876impl<'a> sum_tree::Dimension<'a, ExcerptSummary> for OffsetUtf16 {
4877    fn zero(_cx: &()) -> Self {
4878        Default::default()
4879    }
4880
4881    fn add_summary(&mut self, summary: &'a ExcerptSummary, _: &()) {
4882        *self += summary.text.len_utf16;
4883    }
4884}
4885
4886impl<'a> sum_tree::Dimension<'a, ExcerptSummary> for Point {
4887    fn zero(_cx: &()) -> Self {
4888        Default::default()
4889    }
4890
4891    fn add_summary(&mut self, summary: &'a ExcerptSummary, _: &()) {
4892        *self += summary.text.lines;
4893    }
4894}
4895
4896impl<'a> sum_tree::Dimension<'a, ExcerptSummary> for PointUtf16 {
4897    fn zero(_cx: &()) -> Self {
4898        Default::default()
4899    }
4900
4901    fn add_summary(&mut self, summary: &'a ExcerptSummary, _: &()) {
4902        *self += summary.text.lines_utf16()
4903    }
4904}
4905
4906impl<'a> sum_tree::Dimension<'a, ExcerptSummary> for Option<&'a Locator> {
4907    fn zero(_cx: &()) -> Self {
4908        Default::default()
4909    }
4910
4911    fn add_summary(&mut self, summary: &'a ExcerptSummary, _: &()) {
4912        *self = Some(&summary.excerpt_locator);
4913    }
4914}
4915
4916impl<'a> sum_tree::Dimension<'a, ExcerptSummary> for Option<ExcerptId> {
4917    fn zero(_cx: &()) -> Self {
4918        Default::default()
4919    }
4920
4921    fn add_summary(&mut self, summary: &'a ExcerptSummary, _: &()) {
4922        *self = Some(summary.excerpt_id);
4923    }
4924}
4925
4926impl<'a> MultiBufferRows<'a> {
4927    pub fn seek(&mut self, row: MultiBufferRow) {
4928        self.buffer_row_range = 0..0;
4929
4930        self.excerpts
4931            .seek_forward(&Point::new(row.0, 0), Bias::Right, &());
4932        if self.excerpts.item().is_none() {
4933            self.excerpts.prev(&());
4934
4935            if self.excerpts.item().is_none() && row.0 == 0 {
4936                self.buffer_row_range = 0..1;
4937                return;
4938            }
4939        }
4940
4941        if let Some(excerpt) = self.excerpts.item() {
4942            let overshoot = row.0 - self.excerpts.start().row;
4943            let excerpt_start = excerpt.range.context.start.to_point(&excerpt.buffer).row;
4944            self.buffer_row_range.start = excerpt_start + overshoot;
4945            self.buffer_row_range.end = excerpt_start + excerpt.text_summary.lines.row + 1;
4946        }
4947    }
4948}
4949
4950impl<'a> Iterator for MultiBufferRows<'a> {
4951    type Item = Option<u32>;
4952
4953    fn next(&mut self) -> Option<Self::Item> {
4954        loop {
4955            if !self.buffer_row_range.is_empty() {
4956                let row = Some(self.buffer_row_range.start);
4957                self.buffer_row_range.start += 1;
4958                return Some(row);
4959            }
4960            self.excerpts.item()?;
4961            self.excerpts.next(&());
4962            let excerpt = self.excerpts.item()?;
4963            self.buffer_row_range.start = excerpt.range.context.start.to_point(&excerpt.buffer).row;
4964            self.buffer_row_range.end =
4965                self.buffer_row_range.start + excerpt.text_summary.lines.row + 1;
4966        }
4967    }
4968}
4969
4970impl<'a> MultiBufferChunks<'a> {
4971    pub fn offset(&self) -> usize {
4972        self.range.start
4973    }
4974
4975    pub fn seek(&mut self, new_range: Range<usize>) {
4976        self.range = new_range.clone();
4977        self.excerpts.seek(&new_range.start, Bias::Right, &());
4978        if let Some(excerpt) = self.excerpts.item() {
4979            let excerpt_start = self.excerpts.start();
4980            if let Some(excerpt_chunks) = self
4981                .excerpt_chunks
4982                .as_mut()
4983                .filter(|chunks| excerpt.id == chunks.excerpt_id)
4984            {
4985                excerpt.seek_chunks(
4986                    excerpt_chunks,
4987                    self.range.start - excerpt_start..self.range.end - excerpt_start,
4988                );
4989            } else {
4990                self.excerpt_chunks = Some(excerpt.chunks_in_range(
4991                    self.range.start - excerpt_start..self.range.end - excerpt_start,
4992                    self.language_aware,
4993                ));
4994            }
4995        } else {
4996            self.excerpt_chunks = None;
4997        }
4998    }
4999}
5000
5001impl<'a> Iterator for MultiBufferChunks<'a> {
5002    type Item = Chunk<'a>;
5003
5004    fn next(&mut self) -> Option<Self::Item> {
5005        if self.range.is_empty() {
5006            None
5007        } else if let Some(chunk) = self.excerpt_chunks.as_mut()?.next() {
5008            self.range.start += chunk.text.len();
5009            Some(chunk)
5010        } else {
5011            self.excerpts.next(&());
5012            let excerpt = self.excerpts.item()?;
5013            self.excerpt_chunks = Some(excerpt.chunks_in_range(
5014                0..self.range.end - self.excerpts.start(),
5015                self.language_aware,
5016            ));
5017            self.next()
5018        }
5019    }
5020}
5021
5022impl<'a> MultiBufferBytes<'a> {
5023    fn consume(&mut self, len: usize) {
5024        self.range.start += len;
5025        self.chunk = &self.chunk[len..];
5026
5027        if !self.range.is_empty() && self.chunk.is_empty() {
5028            if let Some(chunk) = self.excerpt_bytes.as_mut().and_then(|bytes| bytes.next()) {
5029                self.chunk = chunk;
5030            } else {
5031                self.excerpts.next(&());
5032                if let Some(excerpt) = self.excerpts.item() {
5033                    let mut excerpt_bytes =
5034                        excerpt.bytes_in_range(0..self.range.end - self.excerpts.start());
5035                    self.chunk = excerpt_bytes.next().unwrap();
5036                    self.excerpt_bytes = Some(excerpt_bytes);
5037                }
5038            }
5039        }
5040    }
5041}
5042
5043impl<'a> Iterator for MultiBufferBytes<'a> {
5044    type Item = &'a [u8];
5045
5046    fn next(&mut self) -> Option<Self::Item> {
5047        let chunk = self.chunk;
5048        if chunk.is_empty() {
5049            None
5050        } else {
5051            self.consume(chunk.len());
5052            Some(chunk)
5053        }
5054    }
5055}
5056
5057impl<'a> io::Read for MultiBufferBytes<'a> {
5058    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
5059        let len = cmp::min(buf.len(), self.chunk.len());
5060        buf[..len].copy_from_slice(&self.chunk[..len]);
5061        if len > 0 {
5062            self.consume(len);
5063        }
5064        Ok(len)
5065    }
5066}
5067
5068impl<'a> ReversedMultiBufferBytes<'a> {
5069    fn consume(&mut self, len: usize) {
5070        self.range.end -= len;
5071        self.chunk = &self.chunk[..self.chunk.len() - len];
5072
5073        if !self.range.is_empty() && self.chunk.is_empty() {
5074            if let Some(chunk) = self.excerpt_bytes.as_mut().and_then(|bytes| bytes.next()) {
5075                self.chunk = chunk;
5076            } else {
5077                self.excerpts.prev(&());
5078                if let Some(excerpt) = self.excerpts.item() {
5079                    let mut excerpt_bytes = excerpt.reversed_bytes_in_range(
5080                        self.range.start.saturating_sub(*self.excerpts.start())..usize::MAX,
5081                    );
5082                    self.chunk = excerpt_bytes.next().unwrap();
5083                    self.excerpt_bytes = Some(excerpt_bytes);
5084                }
5085            }
5086        }
5087    }
5088}
5089
5090impl<'a> io::Read for ReversedMultiBufferBytes<'a> {
5091    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
5092        let len = cmp::min(buf.len(), self.chunk.len());
5093        buf[..len].copy_from_slice(&self.chunk[..len]);
5094        buf[..len].reverse();
5095        if len > 0 {
5096            self.consume(len);
5097        }
5098        Ok(len)
5099    }
5100}
5101impl<'a> Iterator for ExcerptBytes<'a> {
5102    type Item = &'a [u8];
5103
5104    fn next(&mut self) -> Option<Self::Item> {
5105        if self.reversed && self.padding_height > 0 {
5106            let result = &NEWLINES[..self.padding_height];
5107            self.padding_height = 0;
5108            return Some(result);
5109        }
5110
5111        if let Some(chunk) = self.content_bytes.next() {
5112            if !chunk.is_empty() {
5113                return Some(chunk);
5114            }
5115        }
5116
5117        if self.padding_height > 0 {
5118            let result = &NEWLINES[..self.padding_height];
5119            self.padding_height = 0;
5120            return Some(result);
5121        }
5122
5123        None
5124    }
5125}
5126
5127impl<'a> Iterator for ExcerptChunks<'a> {
5128    type Item = Chunk<'a>;
5129
5130    fn next(&mut self) -> Option<Self::Item> {
5131        if let Some(chunk) = self.content_chunks.next() {
5132            return Some(chunk);
5133        }
5134
5135        if self.footer_height > 0 {
5136            let text = unsafe { str::from_utf8_unchecked(&NEWLINES[..self.footer_height]) };
5137            self.footer_height = 0;
5138            return Some(Chunk {
5139                text,
5140                ..Default::default()
5141            });
5142        }
5143
5144        None
5145    }
5146}
5147
5148impl ToOffset for Point {
5149    fn to_offset<'a>(&self, snapshot: &MultiBufferSnapshot) -> usize {
5150        snapshot.point_to_offset(*self)
5151    }
5152}
5153
5154impl ToOffset for usize {
5155    fn to_offset<'a>(&self, snapshot: &MultiBufferSnapshot) -> usize {
5156        assert!(*self <= snapshot.len(), "offset is out of range");
5157        *self
5158    }
5159}
5160
5161impl ToOffset for OffsetUtf16 {
5162    fn to_offset<'a>(&self, snapshot: &MultiBufferSnapshot) -> usize {
5163        snapshot.offset_utf16_to_offset(*self)
5164    }
5165}
5166
5167impl ToOffset for PointUtf16 {
5168    fn to_offset<'a>(&self, snapshot: &MultiBufferSnapshot) -> usize {
5169        snapshot.point_utf16_to_offset(*self)
5170    }
5171}
5172
5173impl ToOffsetUtf16 for OffsetUtf16 {
5174    fn to_offset_utf16(&self, _snapshot: &MultiBufferSnapshot) -> OffsetUtf16 {
5175        *self
5176    }
5177}
5178
5179impl ToOffsetUtf16 for usize {
5180    fn to_offset_utf16(&self, snapshot: &MultiBufferSnapshot) -> OffsetUtf16 {
5181        snapshot.offset_to_offset_utf16(*self)
5182    }
5183}
5184
5185impl ToPoint for usize {
5186    fn to_point<'a>(&self, snapshot: &MultiBufferSnapshot) -> Point {
5187        snapshot.offset_to_point(*self)
5188    }
5189}
5190
5191impl ToPoint for Point {
5192    fn to_point<'a>(&self, _: &MultiBufferSnapshot) -> Point {
5193        *self
5194    }
5195}
5196
5197impl ToPointUtf16 for usize {
5198    fn to_point_utf16<'a>(&self, snapshot: &MultiBufferSnapshot) -> PointUtf16 {
5199        snapshot.offset_to_point_utf16(*self)
5200    }
5201}
5202
5203impl ToPointUtf16 for Point {
5204    fn to_point_utf16<'a>(&self, snapshot: &MultiBufferSnapshot) -> PointUtf16 {
5205        snapshot.point_to_point_utf16(*self)
5206    }
5207}
5208
5209impl ToPointUtf16 for PointUtf16 {
5210    fn to_point_utf16<'a>(&self, _: &MultiBufferSnapshot) -> PointUtf16 {
5211        *self
5212    }
5213}
5214
5215pub fn build_excerpt_ranges<T>(
5216    buffer: &BufferSnapshot,
5217    ranges: &[Range<T>],
5218    context_line_count: u32,
5219) -> (Vec<ExcerptRange<Point>>, Vec<usize>)
5220where
5221    T: text::ToPoint,
5222{
5223    let max_point = buffer.max_point();
5224    let mut range_counts = Vec::new();
5225    let mut excerpt_ranges = Vec::new();
5226    let mut range_iter = ranges
5227        .iter()
5228        .map(|range| range.start.to_point(buffer)..range.end.to_point(buffer))
5229        .peekable();
5230    while let Some(range) = range_iter.next() {
5231        let excerpt_start = Point::new(range.start.row.saturating_sub(context_line_count), 0);
5232        let row = (range.end.row + context_line_count).min(max_point.row);
5233        let mut excerpt_end = Point::new(row, buffer.line_len(row));
5234
5235        let mut ranges_in_excerpt = 1;
5236
5237        while let Some(next_range) = range_iter.peek() {
5238            if next_range.start.row <= excerpt_end.row + context_line_count {
5239                let row = (next_range.end.row + context_line_count).min(max_point.row);
5240                excerpt_end = Point::new(row, buffer.line_len(row));
5241
5242                ranges_in_excerpt += 1;
5243                range_iter.next();
5244            } else {
5245                break;
5246            }
5247        }
5248
5249        excerpt_ranges.push(ExcerptRange {
5250            context: excerpt_start..excerpt_end,
5251            primary: Some(range),
5252        });
5253        range_counts.push(ranges_in_excerpt);
5254    }
5255
5256    (excerpt_ranges, range_counts)
5257}
5258
5259#[cfg(test)]
5260mod tests {
5261    use super::*;
5262    use gpui::{AppContext, Context, TestAppContext};
5263    use language::{Buffer, Rope};
5264    use parking_lot::RwLock;
5265    use rand::prelude::*;
5266    use settings::SettingsStore;
5267    use std::env;
5268    use util::test::sample_text;
5269
5270    #[ctor::ctor]
5271    fn init_logger() {
5272        if std::env::var("RUST_LOG").is_ok() {
5273            env_logger::init();
5274        }
5275    }
5276
5277    #[gpui::test]
5278    fn test_singleton(cx: &mut AppContext) {
5279        let buffer = cx.new_model(|cx| Buffer::local(sample_text(6, 6, 'a'), cx));
5280        let multibuffer = cx.new_model(|cx| MultiBuffer::singleton(buffer.clone(), cx));
5281
5282        let snapshot = multibuffer.read(cx).snapshot(cx);
5283        assert_eq!(snapshot.text(), buffer.read(cx).text());
5284
5285        assert_eq!(
5286            snapshot.buffer_rows(MultiBufferRow(0)).collect::<Vec<_>>(),
5287            (0..buffer.read(cx).row_count())
5288                .map(Some)
5289                .collect::<Vec<_>>()
5290        );
5291
5292        buffer.update(cx, |buffer, cx| buffer.edit([(1..3, "XXX\n")], None, cx));
5293        let snapshot = multibuffer.read(cx).snapshot(cx);
5294
5295        assert_eq!(snapshot.text(), buffer.read(cx).text());
5296        assert_eq!(
5297            snapshot.buffer_rows(MultiBufferRow(0)).collect::<Vec<_>>(),
5298            (0..buffer.read(cx).row_count())
5299                .map(Some)
5300                .collect::<Vec<_>>()
5301        );
5302    }
5303
5304    #[gpui::test]
5305    fn test_remote(cx: &mut AppContext) {
5306        let host_buffer = cx.new_model(|cx| Buffer::local("a", cx));
5307        let guest_buffer = cx.new_model(|cx| {
5308            let state = host_buffer.read(cx).to_proto(cx);
5309            let ops = cx
5310                .background_executor()
5311                .block(host_buffer.read(cx).serialize_ops(None, cx));
5312            let mut buffer = Buffer::from_proto(1, Capability::ReadWrite, state, None).unwrap();
5313            buffer.apply_ops(
5314                ops.into_iter()
5315                    .map(|op| language::proto::deserialize_operation(op).unwrap()),
5316                cx,
5317            );
5318            buffer
5319        });
5320        let multibuffer = cx.new_model(|cx| MultiBuffer::singleton(guest_buffer.clone(), cx));
5321        let snapshot = multibuffer.read(cx).snapshot(cx);
5322        assert_eq!(snapshot.text(), "a");
5323
5324        guest_buffer.update(cx, |buffer, cx| buffer.edit([(1..1, "b")], None, cx));
5325        let snapshot = multibuffer.read(cx).snapshot(cx);
5326        assert_eq!(snapshot.text(), "ab");
5327
5328        guest_buffer.update(cx, |buffer, cx| buffer.edit([(2..2, "c")], None, cx));
5329        let snapshot = multibuffer.read(cx).snapshot(cx);
5330        assert_eq!(snapshot.text(), "abc");
5331    }
5332
5333    #[gpui::test]
5334    fn test_excerpt_boundaries_and_clipping(cx: &mut AppContext) {
5335        let buffer_1 = cx.new_model(|cx| Buffer::local(sample_text(6, 6, 'a'), cx));
5336        let buffer_2 = cx.new_model(|cx| Buffer::local(sample_text(6, 6, 'g'), cx));
5337        let multibuffer = cx.new_model(|_| MultiBuffer::new(Capability::ReadWrite));
5338
5339        let events = Arc::new(RwLock::new(Vec::<Event>::new()));
5340        multibuffer.update(cx, |_, cx| {
5341            let events = events.clone();
5342            cx.subscribe(&multibuffer, move |_, _, event, _| {
5343                if let Event::Edited { .. } = event {
5344                    events.write().push(event.clone())
5345                }
5346            })
5347            .detach();
5348        });
5349
5350        let subscription = multibuffer.update(cx, |multibuffer, cx| {
5351            let subscription = multibuffer.subscribe();
5352            multibuffer.push_excerpts(
5353                buffer_1.clone(),
5354                [ExcerptRange {
5355                    context: Point::new(1, 2)..Point::new(2, 5),
5356                    primary: None,
5357                }],
5358                cx,
5359            );
5360            assert_eq!(
5361                subscription.consume().into_inner(),
5362                [Edit {
5363                    old: 0..0,
5364                    new: 0..10
5365                }]
5366            );
5367
5368            multibuffer.push_excerpts(
5369                buffer_1.clone(),
5370                [ExcerptRange {
5371                    context: Point::new(3, 3)..Point::new(4, 4),
5372                    primary: None,
5373                }],
5374                cx,
5375            );
5376            multibuffer.push_excerpts(
5377                buffer_2.clone(),
5378                [ExcerptRange {
5379                    context: Point::new(3, 1)..Point::new(3, 3),
5380                    primary: None,
5381                }],
5382                cx,
5383            );
5384            assert_eq!(
5385                subscription.consume().into_inner(),
5386                [Edit {
5387                    old: 10..10,
5388                    new: 10..22
5389                }]
5390            );
5391
5392            subscription
5393        });
5394
5395        // Adding excerpts emits an edited event.
5396        assert_eq!(
5397            events.read().as_slice(),
5398            &[
5399                Event::Edited {
5400                    singleton_buffer_edited: false
5401                },
5402                Event::Edited {
5403                    singleton_buffer_edited: false
5404                },
5405                Event::Edited {
5406                    singleton_buffer_edited: false
5407                }
5408            ]
5409        );
5410
5411        let snapshot = multibuffer.read(cx).snapshot(cx);
5412        assert_eq!(
5413            snapshot.text(),
5414            concat!(
5415                "bbbb\n",  // Preserve newlines
5416                "ccccc\n", //
5417                "ddd\n",   //
5418                "eeee\n",  //
5419                "jj"       //
5420            )
5421        );
5422        assert_eq!(
5423            snapshot.buffer_rows(MultiBufferRow(0)).collect::<Vec<_>>(),
5424            [Some(1), Some(2), Some(3), Some(4), Some(3)]
5425        );
5426        assert_eq!(
5427            snapshot.buffer_rows(MultiBufferRow(2)).collect::<Vec<_>>(),
5428            [Some(3), Some(4), Some(3)]
5429        );
5430        assert_eq!(
5431            snapshot.buffer_rows(MultiBufferRow(4)).collect::<Vec<_>>(),
5432            [Some(3)]
5433        );
5434        assert_eq!(
5435            snapshot.buffer_rows(MultiBufferRow(5)).collect::<Vec<_>>(),
5436            []
5437        );
5438
5439        assert_eq!(
5440            boundaries_in_range(Point::new(0, 0)..Point::new(4, 2), &snapshot),
5441            &[
5442                (MultiBufferRow(0), "bbbb\nccccc".to_string(), true),
5443                (MultiBufferRow(2), "ddd\neeee".to_string(), false),
5444                (MultiBufferRow(4), "jj".to_string(), true),
5445            ]
5446        );
5447        assert_eq!(
5448            boundaries_in_range(Point::new(0, 0)..Point::new(2, 0), &snapshot),
5449            &[(MultiBufferRow(0), "bbbb\nccccc".to_string(), true)]
5450        );
5451        assert_eq!(
5452            boundaries_in_range(Point::new(1, 0)..Point::new(1, 5), &snapshot),
5453            &[]
5454        );
5455        assert_eq!(
5456            boundaries_in_range(Point::new(1, 0)..Point::new(2, 0), &snapshot),
5457            &[]
5458        );
5459        assert_eq!(
5460            boundaries_in_range(Point::new(1, 0)..Point::new(4, 0), &snapshot),
5461            &[(MultiBufferRow(2), "ddd\neeee".to_string(), false)]
5462        );
5463        assert_eq!(
5464            boundaries_in_range(Point::new(1, 0)..Point::new(4, 0), &snapshot),
5465            &[(MultiBufferRow(2), "ddd\neeee".to_string(), false)]
5466        );
5467        assert_eq!(
5468            boundaries_in_range(Point::new(2, 0)..Point::new(3, 0), &snapshot),
5469            &[(MultiBufferRow(2), "ddd\neeee".to_string(), false)]
5470        );
5471        assert_eq!(
5472            boundaries_in_range(Point::new(4, 0)..Point::new(4, 2), &snapshot),
5473            &[(MultiBufferRow(4), "jj".to_string(), true)]
5474        );
5475        assert_eq!(
5476            boundaries_in_range(Point::new(4, 2)..Point::new(4, 2), &snapshot),
5477            &[]
5478        );
5479
5480        buffer_1.update(cx, |buffer, cx| {
5481            let text = "\n";
5482            buffer.edit(
5483                [
5484                    (Point::new(0, 0)..Point::new(0, 0), text),
5485                    (Point::new(2, 1)..Point::new(2, 3), text),
5486                ],
5487                None,
5488                cx,
5489            );
5490        });
5491
5492        let snapshot = multibuffer.read(cx).snapshot(cx);
5493        assert_eq!(
5494            snapshot.text(),
5495            concat!(
5496                "bbbb\n", // Preserve newlines
5497                "c\n",    //
5498                "cc\n",   //
5499                "ddd\n",  //
5500                "eeee\n", //
5501                "jj"      //
5502            )
5503        );
5504
5505        assert_eq!(
5506            subscription.consume().into_inner(),
5507            [Edit {
5508                old: 6..8,
5509                new: 6..7
5510            }]
5511        );
5512
5513        let snapshot = multibuffer.read(cx).snapshot(cx);
5514        assert_eq!(
5515            snapshot.clip_point(Point::new(0, 5), Bias::Left),
5516            Point::new(0, 4)
5517        );
5518        assert_eq!(
5519            snapshot.clip_point(Point::new(0, 5), Bias::Right),
5520            Point::new(0, 4)
5521        );
5522        assert_eq!(
5523            snapshot.clip_point(Point::new(5, 1), Bias::Right),
5524            Point::new(5, 1)
5525        );
5526        assert_eq!(
5527            snapshot.clip_point(Point::new(5, 2), Bias::Right),
5528            Point::new(5, 2)
5529        );
5530        assert_eq!(
5531            snapshot.clip_point(Point::new(5, 3), Bias::Right),
5532            Point::new(5, 2)
5533        );
5534
5535        let snapshot = multibuffer.update(cx, |multibuffer, cx| {
5536            let (buffer_2_excerpt_id, _) =
5537                multibuffer.excerpts_for_buffer(&buffer_2, cx)[0].clone();
5538            multibuffer.remove_excerpts([buffer_2_excerpt_id], cx);
5539            multibuffer.snapshot(cx)
5540        });
5541
5542        assert_eq!(
5543            snapshot.text(),
5544            concat!(
5545                "bbbb\n", // Preserve newlines
5546                "c\n",    //
5547                "cc\n",   //
5548                "ddd\n",  //
5549                "eeee",   //
5550            )
5551        );
5552
5553        fn boundaries_in_range(
5554            range: Range<Point>,
5555            snapshot: &MultiBufferSnapshot,
5556        ) -> Vec<(MultiBufferRow, String, bool)> {
5557            snapshot
5558                .excerpt_boundaries_in_range(range)
5559                .filter_map(|boundary| {
5560                    let starts_new_buffer = boundary.starts_new_buffer();
5561                    boundary.next.map(|next| {
5562                        (
5563                            boundary.row,
5564                            next.buffer
5565                                .text_for_range(next.range.context)
5566                                .collect::<String>(),
5567                            starts_new_buffer,
5568                        )
5569                    })
5570                })
5571                .collect::<Vec<_>>()
5572        }
5573    }
5574
5575    #[gpui::test]
5576    fn test_excerpt_events(cx: &mut AppContext) {
5577        let buffer_1 = cx.new_model(|cx| Buffer::local(sample_text(10, 3, 'a'), cx));
5578        let buffer_2 = cx.new_model(|cx| Buffer::local(sample_text(10, 3, 'm'), cx));
5579
5580        let leader_multibuffer = cx.new_model(|_| MultiBuffer::new(Capability::ReadWrite));
5581        let follower_multibuffer = cx.new_model(|_| MultiBuffer::new(Capability::ReadWrite));
5582        let follower_edit_event_count = Arc::new(RwLock::new(0));
5583
5584        follower_multibuffer.update(cx, |_, cx| {
5585            let follower_edit_event_count = follower_edit_event_count.clone();
5586            cx.subscribe(
5587                &leader_multibuffer,
5588                move |follower, _, event, cx| match event.clone() {
5589                    Event::ExcerptsAdded {
5590                        buffer,
5591                        predecessor,
5592                        excerpts,
5593                    } => follower.insert_excerpts_with_ids_after(predecessor, buffer, excerpts, cx),
5594                    Event::ExcerptsRemoved { ids } => follower.remove_excerpts(ids, cx),
5595                    Event::Edited { .. } => {
5596                        *follower_edit_event_count.write() += 1;
5597                    }
5598                    _ => {}
5599                },
5600            )
5601            .detach();
5602        });
5603
5604        leader_multibuffer.update(cx, |leader, cx| {
5605            leader.push_excerpts(
5606                buffer_1.clone(),
5607                [
5608                    ExcerptRange {
5609                        context: 0..8,
5610                        primary: None,
5611                    },
5612                    ExcerptRange {
5613                        context: 12..16,
5614                        primary: None,
5615                    },
5616                ],
5617                cx,
5618            );
5619            leader.insert_excerpts_after(
5620                leader.excerpt_ids()[0],
5621                buffer_2.clone(),
5622                [
5623                    ExcerptRange {
5624                        context: 0..5,
5625                        primary: None,
5626                    },
5627                    ExcerptRange {
5628                        context: 10..15,
5629                        primary: None,
5630                    },
5631                ],
5632                cx,
5633            )
5634        });
5635        assert_eq!(
5636            leader_multibuffer.read(cx).snapshot(cx).text(),
5637            follower_multibuffer.read(cx).snapshot(cx).text(),
5638        );
5639        assert_eq!(*follower_edit_event_count.read(), 2);
5640
5641        leader_multibuffer.update(cx, |leader, cx| {
5642            let excerpt_ids = leader.excerpt_ids();
5643            leader.remove_excerpts([excerpt_ids[1], excerpt_ids[3]], cx);
5644        });
5645        assert_eq!(
5646            leader_multibuffer.read(cx).snapshot(cx).text(),
5647            follower_multibuffer.read(cx).snapshot(cx).text(),
5648        );
5649        assert_eq!(*follower_edit_event_count.read(), 3);
5650
5651        // Removing an empty set of excerpts is a noop.
5652        leader_multibuffer.update(cx, |leader, cx| {
5653            leader.remove_excerpts([], cx);
5654        });
5655        assert_eq!(
5656            leader_multibuffer.read(cx).snapshot(cx).text(),
5657            follower_multibuffer.read(cx).snapshot(cx).text(),
5658        );
5659        assert_eq!(*follower_edit_event_count.read(), 3);
5660
5661        // Adding an empty set of excerpts is a noop.
5662        leader_multibuffer.update(cx, |leader, cx| {
5663            leader.push_excerpts::<usize>(buffer_2.clone(), [], cx);
5664        });
5665        assert_eq!(
5666            leader_multibuffer.read(cx).snapshot(cx).text(),
5667            follower_multibuffer.read(cx).snapshot(cx).text(),
5668        );
5669        assert_eq!(*follower_edit_event_count.read(), 3);
5670
5671        leader_multibuffer.update(cx, |leader, cx| {
5672            leader.clear(cx);
5673        });
5674        assert_eq!(
5675            leader_multibuffer.read(cx).snapshot(cx).text(),
5676            follower_multibuffer.read(cx).snapshot(cx).text(),
5677        );
5678        assert_eq!(*follower_edit_event_count.read(), 4);
5679    }
5680
5681    #[gpui::test]
5682    fn test_expand_excerpts(cx: &mut AppContext) {
5683        let buffer = cx.new_model(|cx| Buffer::local(sample_text(20, 3, 'a'), cx));
5684        let multibuffer = cx.new_model(|_| MultiBuffer::new(Capability::ReadWrite));
5685
5686        multibuffer.update(cx, |multibuffer, cx| {
5687            multibuffer.push_excerpts_with_context_lines(
5688                buffer.clone(),
5689                vec![
5690                    // Note that in this test, this first excerpt
5691                    // does not contain a new line
5692                    Point::new(3, 2)..Point::new(3, 3),
5693                    Point::new(7, 1)..Point::new(7, 3),
5694                    Point::new(15, 0)..Point::new(15, 0),
5695                ],
5696                1,
5697                cx,
5698            )
5699        });
5700
5701        let snapshot = multibuffer.read(cx).snapshot(cx);
5702
5703        assert_eq!(
5704            snapshot.text(),
5705            concat!(
5706                "ccc\n", //
5707                "ddd\n", //
5708                "eee",   //
5709                "\n",    // End of excerpt
5710                "ggg\n", //
5711                "hhh\n", //
5712                "iii",   //
5713                "\n",    // End of excerpt
5714                "ooo\n", //
5715                "ppp\n", //
5716                "qqq",   // End of excerpt
5717            )
5718        );
5719        drop(snapshot);
5720
5721        multibuffer.update(cx, |multibuffer, cx| {
5722            multibuffer.expand_excerpts(
5723                multibuffer.excerpt_ids(),
5724                1,
5725                ExpandExcerptDirection::UpAndDown,
5726                cx,
5727            )
5728        });
5729
5730        let snapshot = multibuffer.read(cx).snapshot(cx);
5731
5732        // Expanding context lines causes the line containing 'fff' to appear in two different excerpts.
5733        // We don't attempt to merge them, because removing the excerpt could create inconsistency with other layers
5734        // that are tracking excerpt ids.
5735        assert_eq!(
5736            snapshot.text(),
5737            concat!(
5738                "bbb\n", //
5739                "ccc\n", //
5740                "ddd\n", //
5741                "eee\n", //
5742                "fff\n", // End of excerpt
5743                "fff\n", //
5744                "ggg\n", //
5745                "hhh\n", //
5746                "iii\n", //
5747                "jjj\n", // End of excerpt
5748                "nnn\n", //
5749                "ooo\n", //
5750                "ppp\n", //
5751                "qqq\n", //
5752                "rrr",   // End of excerpt
5753            )
5754        );
5755    }
5756
5757    #[gpui::test]
5758    fn test_push_excerpts_with_context_lines(cx: &mut AppContext) {
5759        let buffer = cx.new_model(|cx| Buffer::local(sample_text(20, 3, 'a'), cx));
5760        let multibuffer = cx.new_model(|_| MultiBuffer::new(Capability::ReadWrite));
5761        let anchor_ranges = multibuffer.update(cx, |multibuffer, cx| {
5762            multibuffer.push_excerpts_with_context_lines(
5763                buffer.clone(),
5764                vec![
5765                    // Note that in this test, this first excerpt
5766                    // does contain a new line
5767                    Point::new(3, 2)..Point::new(4, 2),
5768                    Point::new(7, 1)..Point::new(7, 3),
5769                    Point::new(15, 0)..Point::new(15, 0),
5770                ],
5771                2,
5772                cx,
5773            )
5774        });
5775
5776        let snapshot = multibuffer.read(cx).snapshot(cx);
5777        assert_eq!(
5778            snapshot.text(),
5779            concat!(
5780                "bbb\n", // Preserve newlines
5781                "ccc\n", //
5782                "ddd\n", //
5783                "eee\n", //
5784                "fff\n", //
5785                "ggg\n", //
5786                "hhh\n", //
5787                "iii\n", //
5788                "jjj\n", //
5789                "nnn\n", //
5790                "ooo\n", //
5791                "ppp\n", //
5792                "qqq\n", //
5793                "rrr",   //
5794            )
5795        );
5796
5797        assert_eq!(
5798            anchor_ranges
5799                .iter()
5800                .map(|range| range.to_point(&snapshot))
5801                .collect::<Vec<_>>(),
5802            vec![
5803                Point::new(2, 2)..Point::new(3, 2),
5804                Point::new(6, 1)..Point::new(6, 3),
5805                Point::new(11, 0)..Point::new(11, 0)
5806            ]
5807        );
5808    }
5809
5810    #[gpui::test(iterations = 100)]
5811    async fn test_push_multiple_excerpts_with_context_lines(cx: &mut TestAppContext) {
5812        let buffer_1 = cx.new_model(|cx| Buffer::local(sample_text(20, 3, 'a'), cx));
5813        let buffer_2 = cx.new_model(|cx| Buffer::local(sample_text(15, 4, 'a'), cx));
5814        let snapshot_1 = buffer_1.update(cx, |buffer, _| buffer.snapshot());
5815        let snapshot_2 = buffer_2.update(cx, |buffer, _| buffer.snapshot());
5816        let ranges_1 = vec![
5817            snapshot_1.anchor_before(Point::new(3, 2))..snapshot_1.anchor_before(Point::new(4, 2)),
5818            snapshot_1.anchor_before(Point::new(7, 1))..snapshot_1.anchor_before(Point::new(7, 3)),
5819            snapshot_1.anchor_before(Point::new(15, 0))
5820                ..snapshot_1.anchor_before(Point::new(15, 0)),
5821        ];
5822        let ranges_2 = vec![
5823            snapshot_2.anchor_before(Point::new(2, 1))..snapshot_2.anchor_before(Point::new(3, 1)),
5824            snapshot_2.anchor_before(Point::new(10, 0))
5825                ..snapshot_2.anchor_before(Point::new(10, 2)),
5826        ];
5827
5828        let multibuffer = cx.new_model(|_| MultiBuffer::new(Capability::ReadWrite));
5829        let anchor_ranges = multibuffer
5830            .update(cx, |multibuffer, cx| {
5831                multibuffer.push_multiple_excerpts_with_context_lines(
5832                    vec![(buffer_1.clone(), ranges_1), (buffer_2.clone(), ranges_2)],
5833                    2,
5834                    cx,
5835                )
5836            })
5837            .await;
5838
5839        let snapshot = multibuffer.update(cx, |multibuffer, cx| multibuffer.snapshot(cx));
5840        assert_eq!(
5841            snapshot.text(),
5842            concat!(
5843                "bbb\n", // buffer_1
5844                "ccc\n", //
5845                "ddd\n", // <-- excerpt 1
5846                "eee\n", // <-- excerpt 1
5847                "fff\n", //
5848                "ggg\n", //
5849                "hhh\n", // <-- excerpt 2
5850                "iii\n", //
5851                "jjj\n", //
5852                //
5853                "nnn\n", //
5854                "ooo\n", //
5855                "ppp\n", // <-- excerpt 3
5856                "qqq\n", //
5857                "rrr\n", //
5858                //
5859                "aaaa\n", // buffer 2
5860                "bbbb\n", //
5861                "cccc\n", // <-- excerpt 4
5862                "dddd\n", // <-- excerpt 4
5863                "eeee\n", //
5864                "ffff\n", //
5865                //
5866                "iiii\n", //
5867                "jjjj\n", //
5868                "kkkk\n", // <-- excerpt 5
5869                "llll\n", //
5870                "mmmm",   //
5871            )
5872        );
5873
5874        assert_eq!(
5875            anchor_ranges
5876                .iter()
5877                .map(|range| range.to_point(&snapshot))
5878                .collect::<Vec<_>>(),
5879            vec![
5880                Point::new(2, 2)..Point::new(3, 2),
5881                Point::new(6, 1)..Point::new(6, 3),
5882                Point::new(11, 0)..Point::new(11, 0),
5883                Point::new(16, 1)..Point::new(17, 1),
5884                Point::new(22, 0)..Point::new(22, 2)
5885            ]
5886        );
5887    }
5888
5889    #[gpui::test]
5890    fn test_empty_multibuffer(cx: &mut AppContext) {
5891        let multibuffer = cx.new_model(|_| MultiBuffer::new(Capability::ReadWrite));
5892
5893        let snapshot = multibuffer.read(cx).snapshot(cx);
5894        assert_eq!(snapshot.text(), "");
5895        assert_eq!(
5896            snapshot.buffer_rows(MultiBufferRow(0)).collect::<Vec<_>>(),
5897            &[Some(0)]
5898        );
5899        assert_eq!(
5900            snapshot.buffer_rows(MultiBufferRow(1)).collect::<Vec<_>>(),
5901            &[]
5902        );
5903    }
5904
5905    #[gpui::test]
5906    fn test_singleton_multibuffer_anchors(cx: &mut AppContext) {
5907        let buffer = cx.new_model(|cx| Buffer::local("abcd", cx));
5908        let multibuffer = cx.new_model(|cx| MultiBuffer::singleton(buffer.clone(), cx));
5909        let old_snapshot = multibuffer.read(cx).snapshot(cx);
5910        buffer.update(cx, |buffer, cx| {
5911            buffer.edit([(0..0, "X")], None, cx);
5912            buffer.edit([(5..5, "Y")], None, cx);
5913        });
5914        let new_snapshot = multibuffer.read(cx).snapshot(cx);
5915
5916        assert_eq!(old_snapshot.text(), "abcd");
5917        assert_eq!(new_snapshot.text(), "XabcdY");
5918
5919        assert_eq!(old_snapshot.anchor_before(0).to_offset(&new_snapshot), 0);
5920        assert_eq!(old_snapshot.anchor_after(0).to_offset(&new_snapshot), 1);
5921        assert_eq!(old_snapshot.anchor_before(4).to_offset(&new_snapshot), 5);
5922        assert_eq!(old_snapshot.anchor_after(4).to_offset(&new_snapshot), 6);
5923    }
5924
5925    #[gpui::test]
5926    fn test_multibuffer_anchors(cx: &mut AppContext) {
5927        let buffer_1 = cx.new_model(|cx| Buffer::local("abcd", cx));
5928        let buffer_2 = cx.new_model(|cx| Buffer::local("efghi", cx));
5929        let multibuffer = cx.new_model(|cx| {
5930            let mut multibuffer = MultiBuffer::new(Capability::ReadWrite);
5931            multibuffer.push_excerpts(
5932                buffer_1.clone(),
5933                [ExcerptRange {
5934                    context: 0..4,
5935                    primary: None,
5936                }],
5937                cx,
5938            );
5939            multibuffer.push_excerpts(
5940                buffer_2.clone(),
5941                [ExcerptRange {
5942                    context: 0..5,
5943                    primary: None,
5944                }],
5945                cx,
5946            );
5947            multibuffer
5948        });
5949        let old_snapshot = multibuffer.read(cx).snapshot(cx);
5950
5951        assert_eq!(old_snapshot.anchor_before(0).to_offset(&old_snapshot), 0);
5952        assert_eq!(old_snapshot.anchor_after(0).to_offset(&old_snapshot), 0);
5953        assert_eq!(Anchor::min().to_offset(&old_snapshot), 0);
5954        assert_eq!(Anchor::min().to_offset(&old_snapshot), 0);
5955        assert_eq!(Anchor::max().to_offset(&old_snapshot), 10);
5956        assert_eq!(Anchor::max().to_offset(&old_snapshot), 10);
5957
5958        buffer_1.update(cx, |buffer, cx| {
5959            buffer.edit([(0..0, "W")], None, cx);
5960            buffer.edit([(5..5, "X")], None, cx);
5961        });
5962        buffer_2.update(cx, |buffer, cx| {
5963            buffer.edit([(0..0, "Y")], None, cx);
5964            buffer.edit([(6..6, "Z")], None, cx);
5965        });
5966        let new_snapshot = multibuffer.read(cx).snapshot(cx);
5967
5968        assert_eq!(old_snapshot.text(), "abcd\nefghi");
5969        assert_eq!(new_snapshot.text(), "WabcdX\nYefghiZ");
5970
5971        assert_eq!(old_snapshot.anchor_before(0).to_offset(&new_snapshot), 0);
5972        assert_eq!(old_snapshot.anchor_after(0).to_offset(&new_snapshot), 1);
5973        assert_eq!(old_snapshot.anchor_before(1).to_offset(&new_snapshot), 2);
5974        assert_eq!(old_snapshot.anchor_after(1).to_offset(&new_snapshot), 2);
5975        assert_eq!(old_snapshot.anchor_before(2).to_offset(&new_snapshot), 3);
5976        assert_eq!(old_snapshot.anchor_after(2).to_offset(&new_snapshot), 3);
5977        assert_eq!(old_snapshot.anchor_before(5).to_offset(&new_snapshot), 7);
5978        assert_eq!(old_snapshot.anchor_after(5).to_offset(&new_snapshot), 8);
5979        assert_eq!(old_snapshot.anchor_before(10).to_offset(&new_snapshot), 13);
5980        assert_eq!(old_snapshot.anchor_after(10).to_offset(&new_snapshot), 14);
5981    }
5982
5983    #[gpui::test]
5984    fn test_resolving_anchors_after_replacing_their_excerpts(cx: &mut AppContext) {
5985        let buffer_1 = cx.new_model(|cx| Buffer::local("abcd", cx));
5986        let buffer_2 = cx.new_model(|cx| Buffer::local("ABCDEFGHIJKLMNOP", cx));
5987        let multibuffer = cx.new_model(|_| MultiBuffer::new(Capability::ReadWrite));
5988
5989        // Create an insertion id in buffer 1 that doesn't exist in buffer 2.
5990        // Add an excerpt from buffer 1 that spans this new insertion.
5991        buffer_1.update(cx, |buffer, cx| buffer.edit([(4..4, "123")], None, cx));
5992        let excerpt_id_1 = multibuffer.update(cx, |multibuffer, cx| {
5993            multibuffer
5994                .push_excerpts(
5995                    buffer_1.clone(),
5996                    [ExcerptRange {
5997                        context: 0..7,
5998                        primary: None,
5999                    }],
6000                    cx,
6001                )
6002                .pop()
6003                .unwrap()
6004        });
6005
6006        let snapshot_1 = multibuffer.read(cx).snapshot(cx);
6007        assert_eq!(snapshot_1.text(), "abcd123");
6008
6009        // Replace the buffer 1 excerpt with new excerpts from buffer 2.
6010        let (excerpt_id_2, excerpt_id_3) = multibuffer.update(cx, |multibuffer, cx| {
6011            multibuffer.remove_excerpts([excerpt_id_1], cx);
6012            let mut ids = multibuffer
6013                .push_excerpts(
6014                    buffer_2.clone(),
6015                    [
6016                        ExcerptRange {
6017                            context: 0..4,
6018                            primary: None,
6019                        },
6020                        ExcerptRange {
6021                            context: 6..10,
6022                            primary: None,
6023                        },
6024                        ExcerptRange {
6025                            context: 12..16,
6026                            primary: None,
6027                        },
6028                    ],
6029                    cx,
6030                )
6031                .into_iter();
6032            (ids.next().unwrap(), ids.next().unwrap())
6033        });
6034        let snapshot_2 = multibuffer.read(cx).snapshot(cx);
6035        assert_eq!(snapshot_2.text(), "ABCD\nGHIJ\nMNOP");
6036
6037        // The old excerpt id doesn't get reused.
6038        assert_ne!(excerpt_id_2, excerpt_id_1);
6039
6040        // Resolve some anchors from the previous snapshot in the new snapshot.
6041        // The current excerpts are from a different buffer, so we don't attempt to
6042        // resolve the old text anchor in the new buffer.
6043        assert_eq!(
6044            snapshot_2.summary_for_anchor::<usize>(&snapshot_1.anchor_before(2)),
6045            0
6046        );
6047        assert_eq!(
6048            snapshot_2.summaries_for_anchors::<usize, _>(&[
6049                snapshot_1.anchor_before(2),
6050                snapshot_1.anchor_after(3)
6051            ]),
6052            vec![0, 0]
6053        );
6054
6055        // Refresh anchors from the old snapshot. The return value indicates that both
6056        // anchors lost their original excerpt.
6057        let refresh =
6058            snapshot_2.refresh_anchors(&[snapshot_1.anchor_before(2), snapshot_1.anchor_after(3)]);
6059        assert_eq!(
6060            refresh,
6061            &[
6062                (0, snapshot_2.anchor_before(0), false),
6063                (1, snapshot_2.anchor_after(0), false),
6064            ]
6065        );
6066
6067        // Replace the middle excerpt with a smaller excerpt in buffer 2,
6068        // that intersects the old excerpt.
6069        let excerpt_id_5 = multibuffer.update(cx, |multibuffer, cx| {
6070            multibuffer.remove_excerpts([excerpt_id_3], cx);
6071            multibuffer
6072                .insert_excerpts_after(
6073                    excerpt_id_2,
6074                    buffer_2.clone(),
6075                    [ExcerptRange {
6076                        context: 5..8,
6077                        primary: None,
6078                    }],
6079                    cx,
6080                )
6081                .pop()
6082                .unwrap()
6083        });
6084
6085        let snapshot_3 = multibuffer.read(cx).snapshot(cx);
6086        assert_eq!(snapshot_3.text(), "ABCD\nFGH\nMNOP");
6087        assert_ne!(excerpt_id_5, excerpt_id_3);
6088
6089        // Resolve some anchors from the previous snapshot in the new snapshot.
6090        // The third anchor can't be resolved, since its excerpt has been removed,
6091        // so it resolves to the same position as its predecessor.
6092        let anchors = [
6093            snapshot_2.anchor_before(0),
6094            snapshot_2.anchor_after(2),
6095            snapshot_2.anchor_after(6),
6096            snapshot_2.anchor_after(14),
6097        ];
6098        assert_eq!(
6099            snapshot_3.summaries_for_anchors::<usize, _>(&anchors),
6100            &[0, 2, 9, 13]
6101        );
6102
6103        let new_anchors = snapshot_3.refresh_anchors(&anchors);
6104        assert_eq!(
6105            new_anchors.iter().map(|a| (a.0, a.2)).collect::<Vec<_>>(),
6106            &[(0, true), (1, true), (2, true), (3, true)]
6107        );
6108        assert_eq!(
6109            snapshot_3.summaries_for_anchors::<usize, _>(new_anchors.iter().map(|a| &a.1)),
6110            &[0, 2, 7, 13]
6111        );
6112    }
6113
6114    #[gpui::test(iterations = 100)]
6115    fn test_random_multibuffer(cx: &mut AppContext, mut rng: StdRng) {
6116        let operations = env::var("OPERATIONS")
6117            .map(|i| i.parse().expect("invalid `OPERATIONS` variable"))
6118            .unwrap_or(10);
6119
6120        let mut buffers: Vec<Model<Buffer>> = Vec::new();
6121        let multibuffer = cx.new_model(|_| MultiBuffer::new(Capability::ReadWrite));
6122        let mut excerpt_ids = Vec::<ExcerptId>::new();
6123        let mut expected_excerpts = Vec::<(Model<Buffer>, Range<text::Anchor>)>::new();
6124        let mut anchors = Vec::new();
6125        let mut old_versions = Vec::new();
6126
6127        for _ in 0..operations {
6128            match rng.gen_range(0..100) {
6129                0..=14 if !buffers.is_empty() => {
6130                    let buffer = buffers.choose(&mut rng).unwrap();
6131                    buffer.update(cx, |buf, cx| buf.randomly_edit(&mut rng, 5, cx));
6132                }
6133                15..=19 if !expected_excerpts.is_empty() => {
6134                    multibuffer.update(cx, |multibuffer, cx| {
6135                        let ids = multibuffer.excerpt_ids();
6136                        let mut excerpts = HashSet::default();
6137                        for _ in 0..rng.gen_range(0..ids.len()) {
6138                            excerpts.extend(ids.choose(&mut rng).copied());
6139                        }
6140
6141                        let line_count = rng.gen_range(0..5);
6142
6143                        let excerpt_ixs = excerpts
6144                            .iter()
6145                            .map(|id| excerpt_ids.iter().position(|i| i == id).unwrap())
6146                            .collect::<Vec<_>>();
6147                        log::info!("Expanding excerpts {excerpt_ixs:?} by {line_count} lines");
6148                        multibuffer.expand_excerpts(
6149                            excerpts.iter().cloned(),
6150                            line_count,
6151                            ExpandExcerptDirection::UpAndDown,
6152                            cx,
6153                        );
6154
6155                        if line_count > 0 {
6156                            for id in excerpts {
6157                                let excerpt_ix = excerpt_ids.iter().position(|&i| i == id).unwrap();
6158                                let (buffer, range) = &mut expected_excerpts[excerpt_ix];
6159                                let snapshot = buffer.read(cx).snapshot();
6160                                let mut point_range = range.to_point(&snapshot);
6161                                point_range.start =
6162                                    Point::new(point_range.start.row.saturating_sub(line_count), 0);
6163                                point_range.end = snapshot.clip_point(
6164                                    Point::new(point_range.end.row + line_count, 0),
6165                                    Bias::Left,
6166                                );
6167                                point_range.end.column = snapshot.line_len(point_range.end.row);
6168                                *range = snapshot.anchor_before(point_range.start)
6169                                    ..snapshot.anchor_after(point_range.end);
6170                            }
6171                        }
6172                    });
6173                }
6174                20..=29 if !expected_excerpts.is_empty() => {
6175                    let mut ids_to_remove = vec![];
6176                    for _ in 0..rng.gen_range(1..=3) {
6177                        if expected_excerpts.is_empty() {
6178                            break;
6179                        }
6180
6181                        let ix = rng.gen_range(0..expected_excerpts.len());
6182                        ids_to_remove.push(excerpt_ids.remove(ix));
6183                        let (buffer, range) = expected_excerpts.remove(ix);
6184                        let buffer = buffer.read(cx);
6185                        log::info!(
6186                            "Removing excerpt {}: {:?}",
6187                            ix,
6188                            buffer
6189                                .text_for_range(range.to_offset(buffer))
6190                                .collect::<String>(),
6191                        );
6192                    }
6193                    let snapshot = multibuffer.read(cx).read(cx);
6194                    ids_to_remove.sort_unstable_by(|a, b| a.cmp(b, &snapshot));
6195                    drop(snapshot);
6196                    multibuffer.update(cx, |multibuffer, cx| {
6197                        multibuffer.remove_excerpts(ids_to_remove, cx)
6198                    });
6199                }
6200                30..=39 if !expected_excerpts.is_empty() => {
6201                    let multibuffer = multibuffer.read(cx).read(cx);
6202                    let offset =
6203                        multibuffer.clip_offset(rng.gen_range(0..=multibuffer.len()), Bias::Left);
6204                    let bias = if rng.gen() { Bias::Left } else { Bias::Right };
6205                    log::info!("Creating anchor at {} with bias {:?}", offset, bias);
6206                    anchors.push(multibuffer.anchor_at(offset, bias));
6207                    anchors.sort_by(|a, b| a.cmp(b, &multibuffer));
6208                }
6209                40..=44 if !anchors.is_empty() => {
6210                    let multibuffer = multibuffer.read(cx).read(cx);
6211                    let prev_len = anchors.len();
6212                    anchors = multibuffer
6213                        .refresh_anchors(&anchors)
6214                        .into_iter()
6215                        .map(|a| a.1)
6216                        .collect();
6217
6218                    // Ensure the newly-refreshed anchors point to a valid excerpt and don't
6219                    // overshoot its boundaries.
6220                    assert_eq!(anchors.len(), prev_len);
6221                    for anchor in &anchors {
6222                        if anchor.excerpt_id == ExcerptId::min()
6223                            || anchor.excerpt_id == ExcerptId::max()
6224                        {
6225                            continue;
6226                        }
6227
6228                        let excerpt = multibuffer.excerpt(anchor.excerpt_id).unwrap();
6229                        assert_eq!(excerpt.id, anchor.excerpt_id);
6230                        assert!(excerpt.contains(anchor));
6231                    }
6232                }
6233                _ => {
6234                    let buffer_handle = if buffers.is_empty() || rng.gen_bool(0.4) {
6235                        let base_text = util::RandomCharIter::new(&mut rng)
6236                            .take(25)
6237                            .collect::<String>();
6238
6239                        buffers.push(cx.new_model(|cx| Buffer::local(base_text, cx)));
6240                        buffers.last().unwrap()
6241                    } else {
6242                        buffers.choose(&mut rng).unwrap()
6243                    };
6244
6245                    let buffer = buffer_handle.read(cx);
6246                    let end_ix = buffer.clip_offset(rng.gen_range(0..=buffer.len()), Bias::Right);
6247                    let start_ix = buffer.clip_offset(rng.gen_range(0..=end_ix), Bias::Left);
6248                    let anchor_range = buffer.anchor_before(start_ix)..buffer.anchor_after(end_ix);
6249                    let prev_excerpt_ix = rng.gen_range(0..=expected_excerpts.len());
6250                    let prev_excerpt_id = excerpt_ids
6251                        .get(prev_excerpt_ix)
6252                        .cloned()
6253                        .unwrap_or_else(ExcerptId::max);
6254                    let excerpt_ix = (prev_excerpt_ix + 1).min(expected_excerpts.len());
6255
6256                    log::info!(
6257                        "Inserting excerpt at {} of {} for buffer {}: {:?}[{:?}] = {:?}",
6258                        excerpt_ix,
6259                        expected_excerpts.len(),
6260                        buffer_handle.read(cx).remote_id(),
6261                        buffer.text(),
6262                        start_ix..end_ix,
6263                        &buffer.text()[start_ix..end_ix]
6264                    );
6265
6266                    let excerpt_id = multibuffer.update(cx, |multibuffer, cx| {
6267                        multibuffer
6268                            .insert_excerpts_after(
6269                                prev_excerpt_id,
6270                                buffer_handle.clone(),
6271                                [ExcerptRange {
6272                                    context: start_ix..end_ix,
6273                                    primary: None,
6274                                }],
6275                                cx,
6276                            )
6277                            .pop()
6278                            .unwrap()
6279                    });
6280
6281                    excerpt_ids.insert(excerpt_ix, excerpt_id);
6282                    expected_excerpts.insert(excerpt_ix, (buffer_handle.clone(), anchor_range));
6283                }
6284            }
6285
6286            if rng.gen_bool(0.3) {
6287                multibuffer.update(cx, |multibuffer, cx| {
6288                    old_versions.push((multibuffer.snapshot(cx), multibuffer.subscribe()));
6289                })
6290            }
6291
6292            let snapshot = multibuffer.read(cx).snapshot(cx);
6293
6294            let mut excerpt_starts = Vec::new();
6295            let mut expected_text = String::new();
6296            let mut expected_buffer_rows = Vec::new();
6297            for (buffer, range) in &expected_excerpts {
6298                let buffer = buffer.read(cx);
6299                let buffer_range = range.to_offset(buffer);
6300
6301                excerpt_starts.push(TextSummary::from(expected_text.as_str()));
6302                expected_text.extend(buffer.text_for_range(buffer_range.clone()));
6303                expected_text.push('\n');
6304
6305                let buffer_row_range = buffer.offset_to_point(buffer_range.start).row
6306                    ..=buffer.offset_to_point(buffer_range.end).row;
6307                for row in buffer_row_range {
6308                    expected_buffer_rows.push(Some(row));
6309                }
6310            }
6311            // Remove final trailing newline.
6312            if !expected_excerpts.is_empty() {
6313                expected_text.pop();
6314            }
6315
6316            // Always report one buffer row
6317            if expected_buffer_rows.is_empty() {
6318                expected_buffer_rows.push(Some(0));
6319            }
6320
6321            assert_eq!(snapshot.text(), expected_text);
6322            log::info!("MultiBuffer text: {:?}", expected_text);
6323
6324            assert_eq!(
6325                snapshot.buffer_rows(MultiBufferRow(0)).collect::<Vec<_>>(),
6326                expected_buffer_rows,
6327            );
6328
6329            for _ in 0..5 {
6330                let start_row = rng.gen_range(0..=expected_buffer_rows.len());
6331                assert_eq!(
6332                    snapshot
6333                        .buffer_rows(MultiBufferRow(start_row as u32))
6334                        .collect::<Vec<_>>(),
6335                    &expected_buffer_rows[start_row..],
6336                    "buffer_rows({})",
6337                    start_row
6338                );
6339            }
6340
6341            assert_eq!(
6342                snapshot.max_buffer_row().0,
6343                expected_buffer_rows.into_iter().flatten().max().unwrap()
6344            );
6345
6346            let mut excerpt_starts = excerpt_starts.into_iter();
6347            for (buffer, range) in &expected_excerpts {
6348                let buffer = buffer.read(cx);
6349                let buffer_id = buffer.remote_id();
6350                let buffer_range = range.to_offset(buffer);
6351                let buffer_start_point = buffer.offset_to_point(buffer_range.start);
6352                let buffer_start_point_utf16 =
6353                    buffer.text_summary_for_range::<PointUtf16, _>(0..buffer_range.start);
6354
6355                let excerpt_start = excerpt_starts.next().unwrap();
6356                let mut offset = excerpt_start.len;
6357                let mut buffer_offset = buffer_range.start;
6358                let mut point = excerpt_start.lines;
6359                let mut buffer_point = buffer_start_point;
6360                let mut point_utf16 = excerpt_start.lines_utf16();
6361                let mut buffer_point_utf16 = buffer_start_point_utf16;
6362                for ch in buffer
6363                    .snapshot()
6364                    .chunks(buffer_range.clone(), false)
6365                    .flat_map(|c| c.text.chars())
6366                {
6367                    for _ in 0..ch.len_utf8() {
6368                        let left_offset = snapshot.clip_offset(offset, Bias::Left);
6369                        let right_offset = snapshot.clip_offset(offset, Bias::Right);
6370                        let buffer_left_offset = buffer.clip_offset(buffer_offset, Bias::Left);
6371                        let buffer_right_offset = buffer.clip_offset(buffer_offset, Bias::Right);
6372                        assert_eq!(
6373                            left_offset,
6374                            excerpt_start.len + (buffer_left_offset - buffer_range.start),
6375                            "clip_offset({:?}, Left). buffer: {:?}, buffer offset: {:?}",
6376                            offset,
6377                            buffer_id,
6378                            buffer_offset,
6379                        );
6380                        assert_eq!(
6381                            right_offset,
6382                            excerpt_start.len + (buffer_right_offset - buffer_range.start),
6383                            "clip_offset({:?}, Right). buffer: {:?}, buffer offset: {:?}",
6384                            offset,
6385                            buffer_id,
6386                            buffer_offset,
6387                        );
6388
6389                        let left_point = snapshot.clip_point(point, Bias::Left);
6390                        let right_point = snapshot.clip_point(point, Bias::Right);
6391                        let buffer_left_point = buffer.clip_point(buffer_point, Bias::Left);
6392                        let buffer_right_point = buffer.clip_point(buffer_point, Bias::Right);
6393                        assert_eq!(
6394                            left_point,
6395                            excerpt_start.lines + (buffer_left_point - buffer_start_point),
6396                            "clip_point({:?}, Left). buffer: {:?}, buffer point: {:?}",
6397                            point,
6398                            buffer_id,
6399                            buffer_point,
6400                        );
6401                        assert_eq!(
6402                            right_point,
6403                            excerpt_start.lines + (buffer_right_point - buffer_start_point),
6404                            "clip_point({:?}, Right). buffer: {:?}, buffer point: {:?}",
6405                            point,
6406                            buffer_id,
6407                            buffer_point,
6408                        );
6409
6410                        assert_eq!(
6411                            snapshot.point_to_offset(left_point),
6412                            left_offset,
6413                            "point_to_offset({:?})",
6414                            left_point,
6415                        );
6416                        assert_eq!(
6417                            snapshot.offset_to_point(left_offset),
6418                            left_point,
6419                            "offset_to_point({:?})",
6420                            left_offset,
6421                        );
6422
6423                        offset += 1;
6424                        buffer_offset += 1;
6425                        if ch == '\n' {
6426                            point += Point::new(1, 0);
6427                            buffer_point += Point::new(1, 0);
6428                        } else {
6429                            point += Point::new(0, 1);
6430                            buffer_point += Point::new(0, 1);
6431                        }
6432                    }
6433
6434                    for _ in 0..ch.len_utf16() {
6435                        let left_point_utf16 =
6436                            snapshot.clip_point_utf16(Unclipped(point_utf16), Bias::Left);
6437                        let right_point_utf16 =
6438                            snapshot.clip_point_utf16(Unclipped(point_utf16), Bias::Right);
6439                        let buffer_left_point_utf16 =
6440                            buffer.clip_point_utf16(Unclipped(buffer_point_utf16), Bias::Left);
6441                        let buffer_right_point_utf16 =
6442                            buffer.clip_point_utf16(Unclipped(buffer_point_utf16), Bias::Right);
6443                        assert_eq!(
6444                            left_point_utf16,
6445                            excerpt_start.lines_utf16()
6446                                + (buffer_left_point_utf16 - buffer_start_point_utf16),
6447                            "clip_point_utf16({:?}, Left). buffer: {:?}, buffer point_utf16: {:?}",
6448                            point_utf16,
6449                            buffer_id,
6450                            buffer_point_utf16,
6451                        );
6452                        assert_eq!(
6453                            right_point_utf16,
6454                            excerpt_start.lines_utf16()
6455                                + (buffer_right_point_utf16 - buffer_start_point_utf16),
6456                            "clip_point_utf16({:?}, Right). buffer: {:?}, buffer point_utf16: {:?}",
6457                            point_utf16,
6458                            buffer_id,
6459                            buffer_point_utf16,
6460                        );
6461
6462                        if ch == '\n' {
6463                            point_utf16 += PointUtf16::new(1, 0);
6464                            buffer_point_utf16 += PointUtf16::new(1, 0);
6465                        } else {
6466                            point_utf16 += PointUtf16::new(0, 1);
6467                            buffer_point_utf16 += PointUtf16::new(0, 1);
6468                        }
6469                    }
6470                }
6471            }
6472
6473            for (row, line) in expected_text.split('\n').enumerate() {
6474                assert_eq!(
6475                    snapshot.line_len(MultiBufferRow(row as u32)),
6476                    line.len() as u32,
6477                    "line_len({}).",
6478                    row
6479                );
6480            }
6481
6482            let text_rope = Rope::from(expected_text.as_str());
6483            for _ in 0..10 {
6484                let end_ix = text_rope.clip_offset(rng.gen_range(0..=text_rope.len()), Bias::Right);
6485                let start_ix = text_rope.clip_offset(rng.gen_range(0..=end_ix), Bias::Left);
6486
6487                let text_for_range = snapshot
6488                    .text_for_range(start_ix..end_ix)
6489                    .collect::<String>();
6490                assert_eq!(
6491                    text_for_range,
6492                    &expected_text[start_ix..end_ix],
6493                    "incorrect text for range {:?}",
6494                    start_ix..end_ix
6495                );
6496
6497                let excerpted_buffer_ranges = multibuffer
6498                    .read(cx)
6499                    .range_to_buffer_ranges(start_ix..end_ix, cx);
6500                let excerpted_buffers_text = excerpted_buffer_ranges
6501                    .iter()
6502                    .map(|(buffer, buffer_range, _)| {
6503                        buffer
6504                            .read(cx)
6505                            .text_for_range(buffer_range.clone())
6506                            .collect::<String>()
6507                    })
6508                    .collect::<Vec<_>>()
6509                    .join("\n");
6510                assert_eq!(excerpted_buffers_text, text_for_range);
6511                if !expected_excerpts.is_empty() {
6512                    assert!(!excerpted_buffer_ranges.is_empty());
6513                }
6514
6515                let expected_summary = TextSummary::from(&expected_text[start_ix..end_ix]);
6516                assert_eq!(
6517                    snapshot.text_summary_for_range::<TextSummary, _>(start_ix..end_ix),
6518                    expected_summary,
6519                    "incorrect summary for range {:?}",
6520                    start_ix..end_ix
6521                );
6522            }
6523
6524            // Anchor resolution
6525            let summaries = snapshot.summaries_for_anchors::<usize, _>(&anchors);
6526            assert_eq!(anchors.len(), summaries.len());
6527            for (anchor, resolved_offset) in anchors.iter().zip(summaries) {
6528                assert!(resolved_offset <= snapshot.len());
6529                assert_eq!(
6530                    snapshot.summary_for_anchor::<usize>(anchor),
6531                    resolved_offset
6532                );
6533            }
6534
6535            for _ in 0..10 {
6536                let end_ix = text_rope.clip_offset(rng.gen_range(0..=text_rope.len()), Bias::Right);
6537                assert_eq!(
6538                    snapshot.reversed_chars_at(end_ix).collect::<String>(),
6539                    expected_text[..end_ix].chars().rev().collect::<String>(),
6540                );
6541            }
6542
6543            for _ in 0..10 {
6544                let end_ix = rng.gen_range(0..=text_rope.len());
6545                let start_ix = rng.gen_range(0..=end_ix);
6546                assert_eq!(
6547                    snapshot
6548                        .bytes_in_range(start_ix..end_ix)
6549                        .flatten()
6550                        .copied()
6551                        .collect::<Vec<_>>(),
6552                    expected_text.as_bytes()[start_ix..end_ix].to_vec(),
6553                    "bytes_in_range({:?})",
6554                    start_ix..end_ix,
6555                );
6556            }
6557        }
6558
6559        let snapshot = multibuffer.read(cx).snapshot(cx);
6560        for (old_snapshot, subscription) in old_versions {
6561            let edits = subscription.consume().into_inner();
6562
6563            log::info!(
6564                "applying subscription edits to old text: {:?}: {:?}",
6565                old_snapshot.text(),
6566                edits,
6567            );
6568
6569            let mut text = old_snapshot.text();
6570            for edit in edits {
6571                let new_text: String = snapshot.text_for_range(edit.new.clone()).collect();
6572                text.replace_range(edit.new.start..edit.new.start + edit.old.len(), &new_text);
6573            }
6574            assert_eq!(text.to_string(), snapshot.text());
6575        }
6576    }
6577
6578    #[gpui::test]
6579    fn test_history(cx: &mut AppContext) {
6580        let test_settings = SettingsStore::test(cx);
6581        cx.set_global(test_settings);
6582        let group_interval: Duration = Duration::from_millis(1);
6583        let buffer_1 = cx.new_model(|cx| {
6584            let mut buf = Buffer::local("1234", cx);
6585            buf.set_group_interval(group_interval);
6586            buf
6587        });
6588        let buffer_2 = cx.new_model(|cx| {
6589            let mut buf = Buffer::local("5678", cx);
6590            buf.set_group_interval(group_interval);
6591            buf
6592        });
6593        let multibuffer = cx.new_model(|_| MultiBuffer::new(Capability::ReadWrite));
6594        multibuffer.update(cx, |this, _| {
6595            this.history.group_interval = group_interval;
6596        });
6597        multibuffer.update(cx, |multibuffer, cx| {
6598            multibuffer.push_excerpts(
6599                buffer_1.clone(),
6600                [ExcerptRange {
6601                    context: 0..buffer_1.read(cx).len(),
6602                    primary: None,
6603                }],
6604                cx,
6605            );
6606            multibuffer.push_excerpts(
6607                buffer_2.clone(),
6608                [ExcerptRange {
6609                    context: 0..buffer_2.read(cx).len(),
6610                    primary: None,
6611                }],
6612                cx,
6613            );
6614        });
6615
6616        let mut now = Instant::now();
6617
6618        multibuffer.update(cx, |multibuffer, cx| {
6619            let transaction_1 = multibuffer.start_transaction_at(now, cx).unwrap();
6620            multibuffer.edit(
6621                [
6622                    (Point::new(0, 0)..Point::new(0, 0), "A"),
6623                    (Point::new(1, 0)..Point::new(1, 0), "A"),
6624                ],
6625                None,
6626                cx,
6627            );
6628            multibuffer.edit(
6629                [
6630                    (Point::new(0, 1)..Point::new(0, 1), "B"),
6631                    (Point::new(1, 1)..Point::new(1, 1), "B"),
6632                ],
6633                None,
6634                cx,
6635            );
6636            multibuffer.end_transaction_at(now, cx);
6637            assert_eq!(multibuffer.read(cx).text(), "AB1234\nAB5678");
6638
6639            // Verify edited ranges for transaction 1
6640            assert_eq!(
6641                multibuffer.edited_ranges_for_transaction(transaction_1, cx),
6642                &[
6643                    Point::new(0, 0)..Point::new(0, 2),
6644                    Point::new(1, 0)..Point::new(1, 2)
6645                ]
6646            );
6647
6648            // Edit buffer 1 through the multibuffer
6649            now += 2 * group_interval;
6650            multibuffer.start_transaction_at(now, cx);
6651            multibuffer.edit([(2..2, "C")], None, cx);
6652            multibuffer.end_transaction_at(now, cx);
6653            assert_eq!(multibuffer.read(cx).text(), "ABC1234\nAB5678");
6654
6655            // Edit buffer 1 independently
6656            buffer_1.update(cx, |buffer_1, cx| {
6657                buffer_1.start_transaction_at(now);
6658                buffer_1.edit([(3..3, "D")], None, cx);
6659                buffer_1.end_transaction_at(now, cx);
6660
6661                now += 2 * group_interval;
6662                buffer_1.start_transaction_at(now);
6663                buffer_1.edit([(4..4, "E")], None, cx);
6664                buffer_1.end_transaction_at(now, cx);
6665            });
6666            assert_eq!(multibuffer.read(cx).text(), "ABCDE1234\nAB5678");
6667
6668            // An undo in the multibuffer undoes the multibuffer transaction
6669            // and also any individual buffer edits that have occurred since
6670            // that transaction.
6671            multibuffer.undo(cx);
6672            assert_eq!(multibuffer.read(cx).text(), "AB1234\nAB5678");
6673
6674            multibuffer.undo(cx);
6675            assert_eq!(multibuffer.read(cx).text(), "1234\n5678");
6676
6677            multibuffer.redo(cx);
6678            assert_eq!(multibuffer.read(cx).text(), "AB1234\nAB5678");
6679
6680            multibuffer.redo(cx);
6681            assert_eq!(multibuffer.read(cx).text(), "ABCDE1234\nAB5678");
6682
6683            // Undo buffer 2 independently.
6684            buffer_2.update(cx, |buffer_2, cx| buffer_2.undo(cx));
6685            assert_eq!(multibuffer.read(cx).text(), "ABCDE1234\n5678");
6686
6687            // An undo in the multibuffer undoes the components of the
6688            // the last multibuffer transaction that are not already undone.
6689            multibuffer.undo(cx);
6690            assert_eq!(multibuffer.read(cx).text(), "AB1234\n5678");
6691
6692            multibuffer.undo(cx);
6693            assert_eq!(multibuffer.read(cx).text(), "1234\n5678");
6694
6695            multibuffer.redo(cx);
6696            assert_eq!(multibuffer.read(cx).text(), "AB1234\nAB5678");
6697
6698            buffer_1.update(cx, |buffer_1, cx| buffer_1.redo(cx));
6699            assert_eq!(multibuffer.read(cx).text(), "ABCD1234\nAB5678");
6700
6701            // Redo stack gets cleared after an edit.
6702            now += 2 * group_interval;
6703            multibuffer.start_transaction_at(now, cx);
6704            multibuffer.edit([(0..0, "X")], None, cx);
6705            multibuffer.end_transaction_at(now, cx);
6706            assert_eq!(multibuffer.read(cx).text(), "XABCD1234\nAB5678");
6707            multibuffer.redo(cx);
6708            assert_eq!(multibuffer.read(cx).text(), "XABCD1234\nAB5678");
6709            multibuffer.undo(cx);
6710            assert_eq!(multibuffer.read(cx).text(), "ABCD1234\nAB5678");
6711            multibuffer.undo(cx);
6712            assert_eq!(multibuffer.read(cx).text(), "1234\n5678");
6713
6714            // Transactions can be grouped manually.
6715            multibuffer.redo(cx);
6716            multibuffer.redo(cx);
6717            assert_eq!(multibuffer.read(cx).text(), "XABCD1234\nAB5678");
6718            multibuffer.group_until_transaction(transaction_1, cx);
6719            multibuffer.undo(cx);
6720            assert_eq!(multibuffer.read(cx).text(), "1234\n5678");
6721            multibuffer.redo(cx);
6722            assert_eq!(multibuffer.read(cx).text(), "XABCD1234\nAB5678");
6723        });
6724    }
6725
6726    #[gpui::test]
6727    fn test_excerpts_in_ranges_no_ranges(cx: &mut AppContext) {
6728        let buffer_1 = cx.new_model(|cx| Buffer::local(sample_text(6, 6, 'a'), cx));
6729        let buffer_2 = cx.new_model(|cx| Buffer::local(sample_text(6, 6, 'g'), cx));
6730        let multibuffer = cx.new_model(|_| MultiBuffer::new(Capability::ReadWrite));
6731        multibuffer.update(cx, |multibuffer, cx| {
6732            multibuffer.push_excerpts(
6733                buffer_1.clone(),
6734                [ExcerptRange {
6735                    context: 0..buffer_1.read(cx).len(),
6736                    primary: None,
6737                }],
6738                cx,
6739            );
6740            multibuffer.push_excerpts(
6741                buffer_2.clone(),
6742                [ExcerptRange {
6743                    context: 0..buffer_2.read(cx).len(),
6744                    primary: None,
6745                }],
6746                cx,
6747            );
6748        });
6749
6750        let snapshot = multibuffer.update(cx, |multibuffer, cx| multibuffer.snapshot(cx));
6751
6752        let mut excerpts = snapshot.excerpts_in_ranges(iter::from_fn(|| None));
6753
6754        assert!(excerpts.next().is_none());
6755    }
6756
6757    fn validate_excerpts(
6758        actual: &[(ExcerptId, BufferId, Range<Anchor>)],
6759        expected: &Vec<(ExcerptId, BufferId, Range<Anchor>)>,
6760    ) {
6761        assert_eq!(actual.len(), expected.len());
6762
6763        actual
6764            .iter()
6765            .zip(expected)
6766            .map(|(actual, expected)| {
6767                assert_eq!(actual.0, expected.0);
6768                assert_eq!(actual.1, expected.1);
6769                assert_eq!(actual.2.start, expected.2.start);
6770                assert_eq!(actual.2.end, expected.2.end);
6771            })
6772            .collect_vec();
6773    }
6774
6775    fn map_range_from_excerpt(
6776        snapshot: &MultiBufferSnapshot,
6777        excerpt_id: ExcerptId,
6778        excerpt_buffer: &BufferSnapshot,
6779        range: Range<usize>,
6780    ) -> Range<Anchor> {
6781        snapshot
6782            .anchor_in_excerpt(excerpt_id, excerpt_buffer.anchor_before(range.start))
6783            .unwrap()
6784            ..snapshot
6785                .anchor_in_excerpt(excerpt_id, excerpt_buffer.anchor_after(range.end))
6786                .unwrap()
6787    }
6788
6789    fn make_expected_excerpt_info(
6790        snapshot: &MultiBufferSnapshot,
6791        cx: &mut AppContext,
6792        excerpt_id: ExcerptId,
6793        buffer: &Model<Buffer>,
6794        range: Range<usize>,
6795    ) -> (ExcerptId, BufferId, Range<Anchor>) {
6796        (
6797            excerpt_id,
6798            buffer.read(cx).remote_id(),
6799            map_range_from_excerpt(snapshot, excerpt_id, &buffer.read(cx).snapshot(), range),
6800        )
6801    }
6802
6803    #[gpui::test]
6804    fn test_excerpts_in_ranges_range_inside_the_excerpt(cx: &mut AppContext) {
6805        let buffer_1 = cx.new_model(|cx| Buffer::local(sample_text(6, 6, 'a'), cx));
6806        let buffer_2 = cx.new_model(|cx| Buffer::local(sample_text(6, 6, 'g'), cx));
6807        let buffer_len = buffer_1.read(cx).len();
6808        let multibuffer = cx.new_model(|_| MultiBuffer::new(Capability::ReadWrite));
6809        let mut expected_excerpt_id = ExcerptId(0);
6810
6811        multibuffer.update(cx, |multibuffer, cx| {
6812            expected_excerpt_id = multibuffer.push_excerpts(
6813                buffer_1.clone(),
6814                [ExcerptRange {
6815                    context: 0..buffer_1.read(cx).len(),
6816                    primary: None,
6817                }],
6818                cx,
6819            )[0];
6820            multibuffer.push_excerpts(
6821                buffer_2.clone(),
6822                [ExcerptRange {
6823                    context: 0..buffer_2.read(cx).len(),
6824                    primary: None,
6825                }],
6826                cx,
6827            );
6828        });
6829
6830        let snapshot = multibuffer.update(cx, |multibuffer, cx| multibuffer.snapshot(cx));
6831
6832        let range = snapshot
6833            .anchor_in_excerpt(expected_excerpt_id, buffer_1.read(cx).anchor_before(1))
6834            .unwrap()
6835            ..snapshot
6836                .anchor_in_excerpt(
6837                    expected_excerpt_id,
6838                    buffer_1.read(cx).anchor_after(buffer_len / 2),
6839                )
6840                .unwrap();
6841
6842        let expected_excerpts = vec![make_expected_excerpt_info(
6843            &snapshot,
6844            cx,
6845            expected_excerpt_id,
6846            &buffer_1,
6847            1..(buffer_len / 2),
6848        )];
6849
6850        let excerpts = snapshot
6851            .excerpts_in_ranges(vec![range.clone()].into_iter())
6852            .map(|(excerpt_id, buffer, actual_range)| {
6853                (
6854                    excerpt_id,
6855                    buffer.remote_id(),
6856                    map_range_from_excerpt(&snapshot, excerpt_id, buffer, actual_range),
6857                )
6858            })
6859            .collect_vec();
6860
6861        validate_excerpts(&excerpts, &expected_excerpts);
6862    }
6863
6864    #[gpui::test]
6865    fn test_excerpts_in_ranges_range_crosses_excerpts_boundary(cx: &mut AppContext) {
6866        let buffer_1 = cx.new_model(|cx| Buffer::local(sample_text(6, 6, 'a'), cx));
6867        let buffer_2 = cx.new_model(|cx| Buffer::local(sample_text(6, 6, 'g'), cx));
6868        let buffer_len = buffer_1.read(cx).len();
6869        let multibuffer = cx.new_model(|_| MultiBuffer::new(Capability::ReadWrite));
6870        let mut excerpt_1_id = ExcerptId(0);
6871        let mut excerpt_2_id = ExcerptId(0);
6872
6873        multibuffer.update(cx, |multibuffer, cx| {
6874            excerpt_1_id = multibuffer.push_excerpts(
6875                buffer_1.clone(),
6876                [ExcerptRange {
6877                    context: 0..buffer_1.read(cx).len(),
6878                    primary: None,
6879                }],
6880                cx,
6881            )[0];
6882            excerpt_2_id = multibuffer.push_excerpts(
6883                buffer_2.clone(),
6884                [ExcerptRange {
6885                    context: 0..buffer_2.read(cx).len(),
6886                    primary: None,
6887                }],
6888                cx,
6889            )[0];
6890        });
6891
6892        let snapshot = multibuffer.read(cx).snapshot(cx);
6893
6894        let expected_range = snapshot
6895            .anchor_in_excerpt(
6896                excerpt_1_id,
6897                buffer_1.read(cx).anchor_before(buffer_len / 2),
6898            )
6899            .unwrap()
6900            ..snapshot
6901                .anchor_in_excerpt(excerpt_2_id, buffer_2.read(cx).anchor_after(buffer_len / 2))
6902                .unwrap();
6903
6904        let expected_excerpts = vec![
6905            make_expected_excerpt_info(
6906                &snapshot,
6907                cx,
6908                excerpt_1_id,
6909                &buffer_1,
6910                (buffer_len / 2)..buffer_len,
6911            ),
6912            make_expected_excerpt_info(&snapshot, cx, excerpt_2_id, &buffer_2, 0..buffer_len / 2),
6913        ];
6914
6915        let excerpts = snapshot
6916            .excerpts_in_ranges(vec![expected_range.clone()].into_iter())
6917            .map(|(excerpt_id, buffer, actual_range)| {
6918                (
6919                    excerpt_id,
6920                    buffer.remote_id(),
6921                    map_range_from_excerpt(&snapshot, excerpt_id, buffer, actual_range),
6922                )
6923            })
6924            .collect_vec();
6925
6926        validate_excerpts(&excerpts, &expected_excerpts);
6927    }
6928
6929    #[gpui::test]
6930    fn test_excerpts_in_ranges_range_encloses_excerpt(cx: &mut AppContext) {
6931        let buffer_1 = cx.new_model(|cx| Buffer::local(sample_text(6, 6, 'a'), cx));
6932        let buffer_2 = cx.new_model(|cx| Buffer::local(sample_text(6, 6, 'g'), cx));
6933        let buffer_3 = cx.new_model(|cx| Buffer::local(sample_text(6, 6, 'r'), cx));
6934        let buffer_len = buffer_1.read(cx).len();
6935        let multibuffer = cx.new_model(|_| MultiBuffer::new(Capability::ReadWrite));
6936        let mut excerpt_1_id = ExcerptId(0);
6937        let mut excerpt_2_id = ExcerptId(0);
6938        let mut excerpt_3_id = ExcerptId(0);
6939
6940        multibuffer.update(cx, |multibuffer, cx| {
6941            excerpt_1_id = multibuffer.push_excerpts(
6942                buffer_1.clone(),
6943                [ExcerptRange {
6944                    context: 0..buffer_1.read(cx).len(),
6945                    primary: None,
6946                }],
6947                cx,
6948            )[0];
6949            excerpt_2_id = multibuffer.push_excerpts(
6950                buffer_2.clone(),
6951                [ExcerptRange {
6952                    context: 0..buffer_2.read(cx).len(),
6953                    primary: None,
6954                }],
6955                cx,
6956            )[0];
6957            excerpt_3_id = multibuffer.push_excerpts(
6958                buffer_3.clone(),
6959                [ExcerptRange {
6960                    context: 0..buffer_3.read(cx).len(),
6961                    primary: None,
6962                }],
6963                cx,
6964            )[0];
6965        });
6966
6967        let snapshot = multibuffer.read(cx).snapshot(cx);
6968
6969        let expected_range = snapshot
6970            .anchor_in_excerpt(
6971                excerpt_1_id,
6972                buffer_1.read(cx).anchor_before(buffer_len / 2),
6973            )
6974            .unwrap()
6975            ..snapshot
6976                .anchor_in_excerpt(excerpt_3_id, buffer_3.read(cx).anchor_after(buffer_len / 2))
6977                .unwrap();
6978
6979        let expected_excerpts = vec![
6980            make_expected_excerpt_info(
6981                &snapshot,
6982                cx,
6983                excerpt_1_id,
6984                &buffer_1,
6985                (buffer_len / 2)..buffer_len,
6986            ),
6987            make_expected_excerpt_info(&snapshot, cx, excerpt_2_id, &buffer_2, 0..buffer_len),
6988            make_expected_excerpt_info(&snapshot, cx, excerpt_3_id, &buffer_3, 0..buffer_len / 2),
6989        ];
6990
6991        let excerpts = snapshot
6992            .excerpts_in_ranges(vec![expected_range.clone()].into_iter())
6993            .map(|(excerpt_id, buffer, actual_range)| {
6994                (
6995                    excerpt_id,
6996                    buffer.remote_id(),
6997                    map_range_from_excerpt(&snapshot, excerpt_id, buffer, actual_range),
6998                )
6999            })
7000            .collect_vec();
7001
7002        validate_excerpts(&excerpts, &expected_excerpts);
7003    }
7004
7005    #[gpui::test]
7006    fn test_excerpts_in_ranges_multiple_ranges(cx: &mut AppContext) {
7007        let buffer_1 = cx.new_model(|cx| Buffer::local(sample_text(6, 6, 'a'), cx));
7008        let buffer_2 = cx.new_model(|cx| Buffer::local(sample_text(6, 6, 'g'), cx));
7009        let buffer_len = buffer_1.read(cx).len();
7010        let multibuffer = cx.new_model(|_| MultiBuffer::new(Capability::ReadWrite));
7011        let mut excerpt_1_id = ExcerptId(0);
7012        let mut excerpt_2_id = ExcerptId(0);
7013
7014        multibuffer.update(cx, |multibuffer, cx| {
7015            excerpt_1_id = multibuffer.push_excerpts(
7016                buffer_1.clone(),
7017                [ExcerptRange {
7018                    context: 0..buffer_1.read(cx).len(),
7019                    primary: None,
7020                }],
7021                cx,
7022            )[0];
7023            excerpt_2_id = multibuffer.push_excerpts(
7024                buffer_2.clone(),
7025                [ExcerptRange {
7026                    context: 0..buffer_2.read(cx).len(),
7027                    primary: None,
7028                }],
7029                cx,
7030            )[0];
7031        });
7032
7033        let snapshot = multibuffer.read(cx).snapshot(cx);
7034
7035        let ranges = vec![
7036            1..(buffer_len / 4),
7037            (buffer_len / 3)..(buffer_len / 2),
7038            (buffer_len / 4 * 3)..(buffer_len),
7039        ];
7040
7041        let expected_excerpts = ranges
7042            .iter()
7043            .map(|range| {
7044                make_expected_excerpt_info(&snapshot, cx, excerpt_1_id, &buffer_1, range.clone())
7045            })
7046            .collect_vec();
7047
7048        let ranges = ranges.into_iter().map(|range| {
7049            map_range_from_excerpt(
7050                &snapshot,
7051                excerpt_1_id,
7052                &buffer_1.read(cx).snapshot(),
7053                range,
7054            )
7055        });
7056
7057        let excerpts = snapshot
7058            .excerpts_in_ranges(ranges)
7059            .map(|(excerpt_id, buffer, actual_range)| {
7060                (
7061                    excerpt_id,
7062                    buffer.remote_id(),
7063                    map_range_from_excerpt(&snapshot, excerpt_id, buffer, actual_range),
7064                )
7065            })
7066            .collect_vec();
7067
7068        validate_excerpts(&excerpts, &expected_excerpts);
7069    }
7070
7071    #[gpui::test]
7072    fn test_excerpts_in_ranges_range_ends_at_excerpt_end(cx: &mut AppContext) {
7073        let buffer_1 = cx.new_model(|cx| Buffer::local(sample_text(6, 6, 'a'), cx));
7074        let buffer_2 = cx.new_model(|cx| Buffer::local(sample_text(6, 6, 'g'), cx));
7075        let buffer_len = buffer_1.read(cx).len();
7076        let multibuffer = cx.new_model(|_| MultiBuffer::new(Capability::ReadWrite));
7077        let mut excerpt_1_id = ExcerptId(0);
7078        let mut excerpt_2_id = ExcerptId(0);
7079
7080        multibuffer.update(cx, |multibuffer, cx| {
7081            excerpt_1_id = multibuffer.push_excerpts(
7082                buffer_1.clone(),
7083                [ExcerptRange {
7084                    context: 0..buffer_1.read(cx).len(),
7085                    primary: None,
7086                }],
7087                cx,
7088            )[0];
7089            excerpt_2_id = multibuffer.push_excerpts(
7090                buffer_2.clone(),
7091                [ExcerptRange {
7092                    context: 0..buffer_2.read(cx).len(),
7093                    primary: None,
7094                }],
7095                cx,
7096            )[0];
7097        });
7098
7099        let snapshot = multibuffer.read(cx).snapshot(cx);
7100
7101        let ranges = [0..buffer_len, (buffer_len / 3)..(buffer_len / 2)];
7102
7103        let expected_excerpts = vec![
7104            make_expected_excerpt_info(&snapshot, cx, excerpt_1_id, &buffer_1, ranges[0].clone()),
7105            make_expected_excerpt_info(&snapshot, cx, excerpt_2_id, &buffer_2, ranges[1].clone()),
7106        ];
7107
7108        let ranges = [
7109            map_range_from_excerpt(
7110                &snapshot,
7111                excerpt_1_id,
7112                &buffer_1.read(cx).snapshot(),
7113                ranges[0].clone(),
7114            ),
7115            map_range_from_excerpt(
7116                &snapshot,
7117                excerpt_2_id,
7118                &buffer_2.read(cx).snapshot(),
7119                ranges[1].clone(),
7120            ),
7121        ];
7122
7123        let excerpts = snapshot
7124            .excerpts_in_ranges(ranges.into_iter())
7125            .map(|(excerpt_id, buffer, actual_range)| {
7126                (
7127                    excerpt_id,
7128                    buffer.remote_id(),
7129                    map_range_from_excerpt(&snapshot, excerpt_id, buffer, actual_range),
7130                )
7131            })
7132            .collect_vec();
7133
7134        validate_excerpts(&excerpts, &expected_excerpts);
7135    }
7136
7137    #[gpui::test]
7138    fn test_split_ranges(cx: &mut AppContext) {
7139        let buffer_1 = cx.new_model(|cx| Buffer::local(sample_text(6, 6, 'a'), cx));
7140        let buffer_2 = cx.new_model(|cx| Buffer::local(sample_text(6, 6, 'g'), cx));
7141        let multibuffer = cx.new_model(|_| MultiBuffer::new(Capability::ReadWrite));
7142        multibuffer.update(cx, |multibuffer, cx| {
7143            multibuffer.push_excerpts(
7144                buffer_1.clone(),
7145                [ExcerptRange {
7146                    context: 0..buffer_1.read(cx).len(),
7147                    primary: None,
7148                }],
7149                cx,
7150            );
7151            multibuffer.push_excerpts(
7152                buffer_2.clone(),
7153                [ExcerptRange {
7154                    context: 0..buffer_2.read(cx).len(),
7155                    primary: None,
7156                }],
7157                cx,
7158            );
7159        });
7160
7161        let snapshot = multibuffer.read(cx).snapshot(cx);
7162
7163        let buffer_1_len = buffer_1.read(cx).len();
7164        let buffer_2_len = buffer_2.read(cx).len();
7165        let buffer_1_midpoint = buffer_1_len / 2;
7166        let buffer_2_start = buffer_1_len + '\n'.len_utf8();
7167        let buffer_2_midpoint = buffer_2_start + buffer_2_len / 2;
7168        let total_len = buffer_2_start + buffer_2_len;
7169
7170        let input_ranges = [
7171            0..buffer_1_midpoint,
7172            buffer_1_midpoint..buffer_2_midpoint,
7173            buffer_2_midpoint..total_len,
7174        ]
7175        .map(|range| snapshot.anchor_before(range.start)..snapshot.anchor_after(range.end));
7176
7177        let actual_ranges = snapshot
7178            .split_ranges(input_ranges.into_iter())
7179            .map(|range| range.to_offset(&snapshot))
7180            .collect::<Vec<_>>();
7181
7182        let expected_ranges = vec![
7183            0..buffer_1_midpoint,
7184            buffer_1_midpoint..buffer_1_len,
7185            buffer_2_start..buffer_2_midpoint,
7186            buffer_2_midpoint..total_len,
7187        ];
7188
7189        assert_eq!(actual_ranges, expected_ranges);
7190    }
7191
7192    #[gpui::test]
7193    fn test_split_ranges_single_range_spanning_three_excerpts(cx: &mut AppContext) {
7194        let buffer_1 = cx.new_model(|cx| Buffer::local(sample_text(6, 6, 'a'), cx));
7195        let buffer_2 = cx.new_model(|cx| Buffer::local(sample_text(6, 6, 'g'), cx));
7196        let buffer_3 = cx.new_model(|cx| Buffer::local(sample_text(6, 6, 'm'), cx));
7197        let multibuffer = cx.new_model(|_| MultiBuffer::new(Capability::ReadWrite));
7198        multibuffer.update(cx, |multibuffer, cx| {
7199            multibuffer.push_excerpts(
7200                buffer_1.clone(),
7201                [ExcerptRange {
7202                    context: 0..buffer_1.read(cx).len(),
7203                    primary: None,
7204                }],
7205                cx,
7206            );
7207            multibuffer.push_excerpts(
7208                buffer_2.clone(),
7209                [ExcerptRange {
7210                    context: 0..buffer_2.read(cx).len(),
7211                    primary: None,
7212                }],
7213                cx,
7214            );
7215            multibuffer.push_excerpts(
7216                buffer_3.clone(),
7217                [ExcerptRange {
7218                    context: 0..buffer_3.read(cx).len(),
7219                    primary: None,
7220                }],
7221                cx,
7222            );
7223        });
7224
7225        let snapshot = multibuffer.read(cx).snapshot(cx);
7226
7227        let buffer_1_len = buffer_1.read(cx).len();
7228        let buffer_2_len = buffer_2.read(cx).len();
7229        let buffer_3_len = buffer_3.read(cx).len();
7230        let buffer_2_start = buffer_1_len + '\n'.len_utf8();
7231        let buffer_3_start = buffer_2_start + buffer_2_len + '\n'.len_utf8();
7232        let buffer_1_midpoint = buffer_1_len / 2;
7233        let buffer_3_midpoint = buffer_3_start + buffer_3_len / 2;
7234
7235        let input_range =
7236            snapshot.anchor_before(buffer_1_midpoint)..snapshot.anchor_after(buffer_3_midpoint);
7237
7238        let actual_ranges = snapshot
7239            .split_ranges(std::iter::once(input_range))
7240            .map(|range| range.to_offset(&snapshot))
7241            .collect::<Vec<_>>();
7242
7243        let expected_ranges = vec![
7244            buffer_1_midpoint..buffer_1_len,
7245            buffer_2_start..buffer_2_start + buffer_2_len,
7246            buffer_3_start..buffer_3_midpoint,
7247        ];
7248
7249        assert_eq!(actual_ranges, expected_ranges);
7250    }
7251}