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_before(&self, id: ExcerptId) -> Option<MultiBufferExcerpt<'_>> {
3445        let start_locator = self.excerpt_locator_for_id(id);
3446        let mut cursor = self.excerpts.cursor::<Option<&Locator>>(&());
3447        cursor.seek(&Some(start_locator), Bias::Left, &());
3448        cursor.prev(&());
3449        let excerpt = cursor.item()?;
3450        Some(MultiBufferExcerpt {
3451            excerpt,
3452            excerpt_offset: 0,
3453        })
3454    }
3455
3456    pub fn excerpt_after(&self, id: ExcerptId) -> Option<MultiBufferExcerpt<'_>> {
3457        let start_locator = self.excerpt_locator_for_id(id);
3458        let mut cursor = self.excerpts.cursor::<Option<&Locator>>(&());
3459        cursor.seek(&Some(start_locator), Bias::Left, &());
3460        cursor.next(&());
3461        let excerpt = cursor.item()?;
3462        Some(MultiBufferExcerpt {
3463            excerpt,
3464            excerpt_offset: 0,
3465        })
3466    }
3467
3468    pub fn excerpt_boundaries_in_range<R, T>(
3469        &self,
3470        range: R,
3471    ) -> impl Iterator<Item = ExcerptBoundary> + '_
3472    where
3473        R: RangeBounds<T>,
3474        T: ToOffset,
3475    {
3476        let start_offset;
3477        let start = match range.start_bound() {
3478            Bound::Included(start) => {
3479                start_offset = start.to_offset(self);
3480                Bound::Included(start_offset)
3481            }
3482            Bound::Excluded(start) => {
3483                start_offset = start.to_offset(self);
3484                Bound::Excluded(start_offset)
3485            }
3486            Bound::Unbounded => {
3487                start_offset = 0;
3488                Bound::Unbounded
3489            }
3490        };
3491        let end = match range.end_bound() {
3492            Bound::Included(end) => Bound::Included(end.to_offset(self)),
3493            Bound::Excluded(end) => Bound::Excluded(end.to_offset(self)),
3494            Bound::Unbounded => Bound::Unbounded,
3495        };
3496        let bounds = (start, end);
3497
3498        let mut cursor = self.excerpts.cursor::<(usize, Point)>(&());
3499        cursor.seek(&start_offset, Bias::Right, &());
3500        if cursor.item().is_none() {
3501            cursor.prev(&());
3502        }
3503        if !bounds.contains(&cursor.start().0) {
3504            cursor.next(&());
3505        }
3506
3507        let mut visited_end = false;
3508        std::iter::from_fn(move || {
3509            if self.singleton {
3510                None
3511            } else if bounds.contains(&cursor.start().0) {
3512                let next = cursor.item().map(|excerpt| ExcerptInfo {
3513                    id: excerpt.id,
3514                    buffer: excerpt.buffer.clone(),
3515                    buffer_id: excerpt.buffer_id,
3516                    range: excerpt.range.clone(),
3517                });
3518
3519                if next.is_none() {
3520                    if visited_end {
3521                        return None;
3522                    } else {
3523                        visited_end = true;
3524                    }
3525                }
3526
3527                let prev = cursor.prev_item().map(|prev_excerpt| ExcerptInfo {
3528                    id: prev_excerpt.id,
3529                    buffer: prev_excerpt.buffer.clone(),
3530                    buffer_id: prev_excerpt.buffer_id,
3531                    range: prev_excerpt.range.clone(),
3532                });
3533                let row = MultiBufferRow(cursor.start().1.row);
3534
3535                cursor.next(&());
3536
3537                Some(ExcerptBoundary { row, prev, next })
3538            } else {
3539                None
3540            }
3541        })
3542    }
3543
3544    pub fn edit_count(&self) -> usize {
3545        self.edit_count
3546    }
3547
3548    pub fn non_text_state_update_count(&self) -> usize {
3549        self.non_text_state_update_count
3550    }
3551
3552    /// Returns the smallest enclosing bracket ranges containing the given range or
3553    /// None if no brackets contain range or the range is not contained in a single
3554    /// excerpt
3555    ///
3556    /// Can optionally pass a range_filter to filter the ranges of brackets to consider
3557    pub fn innermost_enclosing_bracket_ranges<T: ToOffset>(
3558        &self,
3559        range: Range<T>,
3560        range_filter: Option<&dyn Fn(Range<usize>, Range<usize>) -> bool>,
3561    ) -> Option<(Range<usize>, Range<usize>)> {
3562        let range = range.start.to_offset(self)..range.end.to_offset(self);
3563        let excerpt = self.excerpt_containing(range.clone())?;
3564
3565        // Filter to ranges contained in the excerpt
3566        let range_filter = |open: Range<usize>, close: Range<usize>| -> bool {
3567            excerpt.contains_buffer_range(open.start..close.end)
3568                && range_filter.map_or(true, |filter| {
3569                    filter(
3570                        excerpt.map_range_from_buffer(open),
3571                        excerpt.map_range_from_buffer(close),
3572                    )
3573                })
3574        };
3575
3576        let (open, close) = excerpt.buffer().innermost_enclosing_bracket_ranges(
3577            excerpt.map_range_to_buffer(range),
3578            Some(&range_filter),
3579        )?;
3580
3581        Some((
3582            excerpt.map_range_from_buffer(open),
3583            excerpt.map_range_from_buffer(close),
3584        ))
3585    }
3586
3587    /// Returns enclosing bracket ranges containing the given range or returns None if the range is
3588    /// not contained in a single excerpt
3589    pub fn enclosing_bracket_ranges<T: ToOffset>(
3590        &self,
3591        range: Range<T>,
3592    ) -> Option<impl Iterator<Item = (Range<usize>, Range<usize>)> + '_> {
3593        let range = range.start.to_offset(self)..range.end.to_offset(self);
3594        let excerpt = self.excerpt_containing(range.clone())?;
3595
3596        Some(
3597            excerpt
3598                .buffer()
3599                .enclosing_bracket_ranges(excerpt.map_range_to_buffer(range))
3600                .filter_map(move |(open, close)| {
3601                    if excerpt.contains_buffer_range(open.start..close.end) {
3602                        Some((
3603                            excerpt.map_range_from_buffer(open),
3604                            excerpt.map_range_from_buffer(close),
3605                        ))
3606                    } else {
3607                        None
3608                    }
3609                }),
3610        )
3611    }
3612
3613    /// Returns bracket range pairs overlapping the given `range` or returns None if the `range` is
3614    /// not contained in a single excerpt
3615    pub fn bracket_ranges<T: ToOffset>(
3616        &self,
3617        range: Range<T>,
3618    ) -> Option<impl Iterator<Item = (Range<usize>, Range<usize>)> + '_> {
3619        let range = range.start.to_offset(self)..range.end.to_offset(self);
3620        let excerpt = self.excerpt_containing(range.clone())?;
3621
3622        Some(
3623            excerpt
3624                .buffer()
3625                .bracket_ranges(excerpt.map_range_to_buffer(range))
3626                .filter_map(move |(start_bracket_range, close_bracket_range)| {
3627                    let buffer_range = start_bracket_range.start..close_bracket_range.end;
3628                    if excerpt.contains_buffer_range(buffer_range) {
3629                        Some((
3630                            excerpt.map_range_from_buffer(start_bracket_range),
3631                            excerpt.map_range_from_buffer(close_bracket_range),
3632                        ))
3633                    } else {
3634                        None
3635                    }
3636                }),
3637        )
3638    }
3639
3640    pub fn redacted_ranges<'a, T: ToOffset>(
3641        &'a self,
3642        range: Range<T>,
3643        redaction_enabled: impl Fn(Option<&Arc<dyn File>>) -> bool + 'a,
3644    ) -> impl Iterator<Item = Range<usize>> + 'a {
3645        let range = range.start.to_offset(self)..range.end.to_offset(self);
3646        self.excerpts_for_range(range.clone())
3647            .filter(move |&(excerpt, _)| redaction_enabled(excerpt.buffer.file()))
3648            .flat_map(move |(excerpt, excerpt_offset)| {
3649                let excerpt_buffer_start = excerpt.range.context.start.to_offset(&excerpt.buffer);
3650
3651                excerpt
3652                    .buffer
3653                    .redacted_ranges(excerpt.range.context.clone())
3654                    .map(move |mut redacted_range| {
3655                        // Re-base onto the excerpts coordinates in the multibuffer
3656                        redacted_range.start = excerpt_offset
3657                            + redacted_range.start.saturating_sub(excerpt_buffer_start);
3658                        redacted_range.end = excerpt_offset
3659                            + redacted_range.end.saturating_sub(excerpt_buffer_start);
3660
3661                        redacted_range
3662                    })
3663                    .skip_while(move |redacted_range| redacted_range.end < range.start)
3664                    .take_while(move |redacted_range| redacted_range.start < range.end)
3665            })
3666    }
3667
3668    pub fn runnable_ranges(
3669        &self,
3670        range: Range<Anchor>,
3671    ) -> impl Iterator<Item = language::RunnableRange> + '_ {
3672        let range = range.start.to_offset(self)..range.end.to_offset(self);
3673        self.excerpts_for_range(range.clone())
3674            .flat_map(move |(excerpt, excerpt_offset)| {
3675                let excerpt_buffer_start = excerpt.range.context.start.to_offset(&excerpt.buffer);
3676
3677                excerpt
3678                    .buffer
3679                    .runnable_ranges(excerpt.range.context.clone())
3680                    .filter_map(move |mut runnable| {
3681                        // Re-base onto the excerpts coordinates in the multibuffer
3682                        //
3683                        // The node matching our runnables query might partially overlap with
3684                        // the provided range. If the run indicator is outside of excerpt bounds, do not actually show it.
3685                        if runnable.run_range.start < excerpt_buffer_start {
3686                            return None;
3687                        }
3688                        if language::ToPoint::to_point(&runnable.run_range.end, &excerpt.buffer).row
3689                            > excerpt.max_buffer_row
3690                        {
3691                            return None;
3692                        }
3693                        runnable.run_range.start =
3694                            excerpt_offset + runnable.run_range.start - excerpt_buffer_start;
3695                        runnable.run_range.end =
3696                            excerpt_offset + runnable.run_range.end - excerpt_buffer_start;
3697                        Some(runnable)
3698                    })
3699                    .skip_while(move |runnable| runnable.run_range.end < range.start)
3700                    .take_while(move |runnable| runnable.run_range.start < range.end)
3701            })
3702    }
3703
3704    pub fn indent_guides_in_range(
3705        &self,
3706        range: Range<Anchor>,
3707        ignore_disabled_for_language: bool,
3708        cx: &AppContext,
3709    ) -> Vec<MultiBufferIndentGuide> {
3710        // Fast path for singleton buffers, we can skip the conversion between offsets.
3711        if let Some((_, _, snapshot)) = self.as_singleton() {
3712            return snapshot
3713                .indent_guides_in_range(
3714                    range.start.text_anchor..range.end.text_anchor,
3715                    ignore_disabled_for_language,
3716                    cx,
3717                )
3718                .into_iter()
3719                .map(|guide| MultiBufferIndentGuide {
3720                    multibuffer_row_range: MultiBufferRow(guide.start_row)
3721                        ..MultiBufferRow(guide.end_row),
3722                    buffer: guide,
3723                })
3724                .collect();
3725        }
3726
3727        let range = range.start.to_offset(self)..range.end.to_offset(self);
3728
3729        self.excerpts_for_range(range.clone())
3730            .flat_map(move |(excerpt, excerpt_offset)| {
3731                let excerpt_buffer_start_row =
3732                    excerpt.range.context.start.to_point(&excerpt.buffer).row;
3733                let excerpt_offset_row = crate::ToPoint::to_point(&excerpt_offset, self).row;
3734
3735                excerpt
3736                    .buffer
3737                    .indent_guides_in_range(
3738                        excerpt.range.context.clone(),
3739                        ignore_disabled_for_language,
3740                        cx,
3741                    )
3742                    .into_iter()
3743                    .map(move |indent_guide| {
3744                        let start_row = excerpt_offset_row
3745                            + (indent_guide.start_row - excerpt_buffer_start_row);
3746                        let end_row =
3747                            excerpt_offset_row + (indent_guide.end_row - excerpt_buffer_start_row);
3748
3749                        MultiBufferIndentGuide {
3750                            multibuffer_row_range: MultiBufferRow(start_row)
3751                                ..MultiBufferRow(end_row),
3752                            buffer: indent_guide,
3753                        }
3754                    })
3755            })
3756            .collect()
3757    }
3758
3759    pub fn trailing_excerpt_update_count(&self) -> usize {
3760        self.trailing_excerpt_update_count
3761    }
3762
3763    pub fn file_at<T: ToOffset>(&self, point: T) -> Option<&Arc<dyn File>> {
3764        self.point_to_buffer_offset(point)
3765            .and_then(|(buffer, _)| buffer.file())
3766    }
3767
3768    pub fn language_at<T: ToOffset>(&self, point: T) -> Option<&Arc<Language>> {
3769        self.point_to_buffer_offset(point)
3770            .and_then(|(buffer, offset)| buffer.language_at(offset))
3771    }
3772
3773    pub fn settings_at<'a, T: ToOffset>(
3774        &'a self,
3775        point: T,
3776        cx: &'a AppContext,
3777    ) -> Cow<'a, LanguageSettings> {
3778        let mut language = None;
3779        let mut file = None;
3780        if let Some((buffer, offset)) = self.point_to_buffer_offset(point) {
3781            language = buffer.language_at(offset);
3782            file = buffer.file();
3783        }
3784        language_settings(language.map(|l| l.name()), file, cx)
3785    }
3786
3787    pub fn language_scope_at<T: ToOffset>(&self, point: T) -> Option<LanguageScope> {
3788        self.point_to_buffer_offset(point)
3789            .and_then(|(buffer, offset)| buffer.language_scope_at(offset))
3790    }
3791
3792    pub fn char_classifier_at<T: ToOffset>(&self, point: T) -> CharClassifier {
3793        self.point_to_buffer_offset(point)
3794            .map(|(buffer, offset)| buffer.char_classifier_at(offset))
3795            .unwrap_or_default()
3796    }
3797
3798    pub fn language_indent_size_at<T: ToOffset>(
3799        &self,
3800        position: T,
3801        cx: &AppContext,
3802    ) -> Option<IndentSize> {
3803        let (buffer_snapshot, offset) = self.point_to_buffer_offset(position)?;
3804        Some(buffer_snapshot.language_indent_size_at(offset, cx))
3805    }
3806
3807    pub fn is_dirty(&self) -> bool {
3808        self.is_dirty
3809    }
3810
3811    pub fn has_deleted_file(&self) -> bool {
3812        self.has_deleted_file
3813    }
3814
3815    pub fn has_conflict(&self) -> bool {
3816        self.has_conflict
3817    }
3818
3819    pub fn has_diagnostics(&self) -> bool {
3820        self.excerpts
3821            .iter()
3822            .any(|excerpt| excerpt.buffer.has_diagnostics())
3823    }
3824
3825    pub fn diagnostic_group<'a, O>(
3826        &'a self,
3827        group_id: usize,
3828    ) -> impl Iterator<Item = DiagnosticEntry<O>> + 'a
3829    where
3830        O: text::FromAnchor + 'a,
3831    {
3832        self.as_singleton()
3833            .into_iter()
3834            .flat_map(move |(_, _, buffer)| buffer.diagnostic_group(group_id))
3835    }
3836
3837    pub fn diagnostics_in_range<'a, T, O>(
3838        &'a self,
3839        range: Range<T>,
3840        reversed: bool,
3841    ) -> impl Iterator<Item = DiagnosticEntry<O>> + 'a
3842    where
3843        T: 'a + ToOffset,
3844        O: 'a + text::FromAnchor + Ord,
3845    {
3846        self.as_singleton()
3847            .into_iter()
3848            .flat_map(move |(_, _, buffer)| {
3849                buffer.diagnostics_in_range(
3850                    range.start.to_offset(self)..range.end.to_offset(self),
3851                    reversed,
3852                )
3853            })
3854    }
3855
3856    pub fn has_git_diffs(&self) -> bool {
3857        for excerpt in self.excerpts.iter() {
3858            if excerpt.buffer.has_git_diff() {
3859                return true;
3860            }
3861        }
3862        false
3863    }
3864
3865    pub fn git_diff_hunks_in_range_rev(
3866        &self,
3867        row_range: Range<MultiBufferRow>,
3868    ) -> impl Iterator<Item = MultiBufferDiffHunk> + '_ {
3869        let mut cursor = self.excerpts.cursor::<Point>(&());
3870
3871        cursor.seek(&Point::new(row_range.end.0, 0), Bias::Left, &());
3872        if cursor.item().is_none() {
3873            cursor.prev(&());
3874        }
3875
3876        std::iter::from_fn(move || {
3877            let excerpt = cursor.item()?;
3878            let multibuffer_start = *cursor.start();
3879            let multibuffer_end = multibuffer_start + excerpt.text_summary.lines;
3880            if multibuffer_start.row >= row_range.end.0 {
3881                return None;
3882            }
3883
3884            let mut buffer_start = excerpt.range.context.start;
3885            let mut buffer_end = excerpt.range.context.end;
3886            let excerpt_start_point = buffer_start.to_point(&excerpt.buffer);
3887            let excerpt_end_point = excerpt_start_point + excerpt.text_summary.lines;
3888
3889            if row_range.start.0 > multibuffer_start.row {
3890                let buffer_start_point =
3891                    excerpt_start_point + Point::new(row_range.start.0 - multibuffer_start.row, 0);
3892                buffer_start = excerpt.buffer.anchor_before(buffer_start_point);
3893            }
3894
3895            if row_range.end.0 < multibuffer_end.row {
3896                let buffer_end_point =
3897                    excerpt_start_point + Point::new(row_range.end.0 - multibuffer_start.row, 0);
3898                buffer_end = excerpt.buffer.anchor_before(buffer_end_point);
3899            }
3900
3901            let buffer_hunks = excerpt
3902                .buffer
3903                .git_diff_hunks_intersecting_range_rev(buffer_start..buffer_end)
3904                .map(move |hunk| {
3905                    let start = multibuffer_start.row
3906                        + hunk.row_range.start.saturating_sub(excerpt_start_point.row);
3907                    let end = multibuffer_start.row
3908                        + hunk
3909                            .row_range
3910                            .end
3911                            .min(excerpt_end_point.row + 1)
3912                            .saturating_sub(excerpt_start_point.row);
3913
3914                    MultiBufferDiffHunk {
3915                        row_range: MultiBufferRow(start)..MultiBufferRow(end),
3916                        diff_base_byte_range: hunk.diff_base_byte_range.clone(),
3917                        buffer_range: hunk.buffer_range.clone(),
3918                        buffer_id: excerpt.buffer_id,
3919                    }
3920                });
3921
3922            cursor.prev(&());
3923
3924            Some(buffer_hunks)
3925        })
3926        .flatten()
3927    }
3928
3929    pub fn git_diff_hunks_in_range(
3930        &self,
3931        row_range: Range<MultiBufferRow>,
3932    ) -> impl Iterator<Item = MultiBufferDiffHunk> + '_ {
3933        let mut cursor = self.excerpts.cursor::<Point>(&());
3934
3935        cursor.seek(&Point::new(row_range.start.0, 0), Bias::Left, &());
3936
3937        std::iter::from_fn(move || {
3938            let excerpt = cursor.item()?;
3939            let multibuffer_start = *cursor.start();
3940            let multibuffer_end = multibuffer_start + excerpt.text_summary.lines;
3941            let mut buffer_start = excerpt.range.context.start;
3942            let mut buffer_end = excerpt.range.context.end;
3943
3944            let excerpt_rows = match multibuffer_start.row.cmp(&row_range.end.0) {
3945                cmp::Ordering::Less => {
3946                    let excerpt_start_point = buffer_start.to_point(&excerpt.buffer);
3947                    let excerpt_end_point = excerpt_start_point + excerpt.text_summary.lines;
3948
3949                    if row_range.start.0 > multibuffer_start.row {
3950                        let buffer_start_point = excerpt_start_point
3951                            + Point::new(row_range.start.0 - multibuffer_start.row, 0);
3952                        buffer_start = excerpt.buffer.anchor_before(buffer_start_point);
3953                    }
3954
3955                    if row_range.end.0 < multibuffer_end.row {
3956                        let buffer_end_point = excerpt_start_point
3957                            + Point::new(row_range.end.0 - multibuffer_start.row, 0);
3958                        buffer_end = excerpt.buffer.anchor_before(buffer_end_point);
3959                    }
3960                    excerpt_start_point.row..excerpt_end_point.row
3961                }
3962                cmp::Ordering::Equal if row_range.end.0 == 0 => {
3963                    buffer_end = buffer_start;
3964                    0..0
3965                }
3966                cmp::Ordering::Greater | cmp::Ordering::Equal => return None,
3967            };
3968
3969            let buffer_hunks = excerpt
3970                .buffer
3971                .git_diff_hunks_intersecting_range(buffer_start..buffer_end)
3972                .map(move |hunk| {
3973                    let buffer_range = if excerpt_rows.start == 0 && excerpt_rows.end == 0 {
3974                        MultiBufferRow(0)..MultiBufferRow(1)
3975                    } else {
3976                        let start = multibuffer_start.row
3977                            + hunk.row_range.start.saturating_sub(excerpt_rows.start);
3978                        let end = multibuffer_start.row
3979                            + hunk
3980                                .row_range
3981                                .end
3982                                .min(excerpt_rows.end + 1)
3983                                .saturating_sub(excerpt_rows.start);
3984                        MultiBufferRow(start)..MultiBufferRow(end)
3985                    };
3986                    MultiBufferDiffHunk {
3987                        row_range: buffer_range,
3988                        diff_base_byte_range: hunk.diff_base_byte_range.clone(),
3989                        buffer_range: hunk.buffer_range.clone(),
3990                        buffer_id: excerpt.buffer_id,
3991                    }
3992                });
3993
3994            cursor.next(&());
3995
3996            Some(buffer_hunks)
3997        })
3998        .flatten()
3999    }
4000
4001    pub fn range_for_syntax_ancestor<T: ToOffset>(&self, range: Range<T>) -> Option<Range<usize>> {
4002        let range = range.start.to_offset(self)..range.end.to_offset(self);
4003        let excerpt = self.excerpt_containing(range.clone())?;
4004
4005        let ancestor_buffer_range = excerpt
4006            .buffer()
4007            .range_for_syntax_ancestor(excerpt.map_range_to_buffer(range))?;
4008
4009        Some(excerpt.map_range_from_buffer(ancestor_buffer_range))
4010    }
4011
4012    pub fn outline(&self, theme: Option<&SyntaxTheme>) -> Option<Outline<Anchor>> {
4013        let (excerpt_id, _, buffer) = self.as_singleton()?;
4014        let outline = buffer.outline(theme)?;
4015        Some(Outline::new(
4016            outline
4017                .items
4018                .into_iter()
4019                .flat_map(|item| {
4020                    Some(OutlineItem {
4021                        depth: item.depth,
4022                        range: self.anchor_in_excerpt(*excerpt_id, item.range.start)?
4023                            ..self.anchor_in_excerpt(*excerpt_id, item.range.end)?,
4024                        text: item.text,
4025                        highlight_ranges: item.highlight_ranges,
4026                        name_ranges: item.name_ranges,
4027                        body_range: item.body_range.and_then(|body_range| {
4028                            Some(
4029                                self.anchor_in_excerpt(*excerpt_id, body_range.start)?
4030                                    ..self.anchor_in_excerpt(*excerpt_id, body_range.end)?,
4031                            )
4032                        }),
4033                        annotation_range: item.annotation_range.and_then(|annotation_range| {
4034                            Some(
4035                                self.anchor_in_excerpt(*excerpt_id, annotation_range.start)?
4036                                    ..self.anchor_in_excerpt(*excerpt_id, annotation_range.end)?,
4037                            )
4038                        }),
4039                    })
4040                })
4041                .collect(),
4042        ))
4043    }
4044
4045    pub fn symbols_containing<T: ToOffset>(
4046        &self,
4047        offset: T,
4048        theme: Option<&SyntaxTheme>,
4049    ) -> Option<(BufferId, Vec<OutlineItem<Anchor>>)> {
4050        let anchor = self.anchor_before(offset);
4051        let excerpt_id = anchor.excerpt_id;
4052        let excerpt = self.excerpt(excerpt_id)?;
4053        Some((
4054            excerpt.buffer_id,
4055            excerpt
4056                .buffer
4057                .symbols_containing(anchor.text_anchor, theme)
4058                .into_iter()
4059                .flatten()
4060                .flat_map(|item| {
4061                    Some(OutlineItem {
4062                        depth: item.depth,
4063                        range: self.anchor_in_excerpt(excerpt_id, item.range.start)?
4064                            ..self.anchor_in_excerpt(excerpt_id, item.range.end)?,
4065                        text: item.text,
4066                        highlight_ranges: item.highlight_ranges,
4067                        name_ranges: item.name_ranges,
4068                        body_range: item.body_range.and_then(|body_range| {
4069                            Some(
4070                                self.anchor_in_excerpt(excerpt_id, body_range.start)?
4071                                    ..self.anchor_in_excerpt(excerpt_id, body_range.end)?,
4072                            )
4073                        }),
4074                        annotation_range: item.annotation_range.and_then(|body_range| {
4075                            Some(
4076                                self.anchor_in_excerpt(excerpt_id, body_range.start)?
4077                                    ..self.anchor_in_excerpt(excerpt_id, body_range.end)?,
4078                            )
4079                        }),
4080                    })
4081                })
4082                .collect(),
4083        ))
4084    }
4085
4086    fn excerpt_locator_for_id(&self, id: ExcerptId) -> &Locator {
4087        if id == ExcerptId::min() {
4088            Locator::min_ref()
4089        } else if id == ExcerptId::max() {
4090            Locator::max_ref()
4091        } else {
4092            let mut cursor = self.excerpt_ids.cursor::<ExcerptId>(&());
4093            cursor.seek(&id, Bias::Left, &());
4094            if let Some(entry) = cursor.item() {
4095                if entry.id == id {
4096                    return &entry.locator;
4097                }
4098            }
4099            panic!("invalid excerpt id {:?}", id)
4100        }
4101    }
4102
4103    /// Returns the locators referenced by the given excerpt IDs, sorted by locator.
4104    fn excerpt_locators_for_ids(
4105        &self,
4106        ids: impl IntoIterator<Item = ExcerptId>,
4107    ) -> SmallVec<[Locator; 1]> {
4108        let mut sorted_ids = ids.into_iter().collect::<SmallVec<[_; 1]>>();
4109        sorted_ids.sort_unstable();
4110        let mut locators = SmallVec::new();
4111
4112        while sorted_ids.last() == Some(&ExcerptId::max()) {
4113            sorted_ids.pop();
4114            if let Some(mapping) = self.excerpt_ids.last() {
4115                locators.push(mapping.locator.clone());
4116            }
4117        }
4118
4119        let mut sorted_ids = sorted_ids.into_iter().dedup().peekable();
4120        if sorted_ids.peek() == Some(&ExcerptId::min()) {
4121            sorted_ids.next();
4122            if let Some(mapping) = self.excerpt_ids.first() {
4123                locators.push(mapping.locator.clone());
4124            }
4125        }
4126
4127        let mut cursor = self.excerpt_ids.cursor::<ExcerptId>(&());
4128        for id in sorted_ids {
4129            if cursor.seek_forward(&id, Bias::Left, &()) {
4130                locators.push(cursor.item().unwrap().locator.clone());
4131            } else {
4132                panic!("invalid excerpt id {:?}", id);
4133            }
4134        }
4135
4136        locators.sort_unstable();
4137        locators
4138    }
4139
4140    pub fn buffer_id_for_excerpt(&self, excerpt_id: ExcerptId) -> Option<BufferId> {
4141        Some(self.excerpt(excerpt_id)?.buffer_id)
4142    }
4143
4144    pub fn buffer_for_excerpt(&self, excerpt_id: ExcerptId) -> Option<&BufferSnapshot> {
4145        Some(&self.excerpt(excerpt_id)?.buffer)
4146    }
4147
4148    pub fn range_for_excerpt<'a, T: sum_tree::Dimension<'a, ExcerptSummary>>(
4149        &'a self,
4150        excerpt_id: ExcerptId,
4151    ) -> Option<Range<T>> {
4152        let mut cursor = self.excerpts.cursor::<(Option<&Locator>, T)>(&());
4153        let locator = self.excerpt_locator_for_id(excerpt_id);
4154        if cursor.seek(&Some(locator), Bias::Left, &()) {
4155            let start = cursor.start().1.clone();
4156            let end = cursor.end(&()).1;
4157            Some(start..end)
4158        } else {
4159            None
4160        }
4161    }
4162
4163    fn excerpt(&self, excerpt_id: ExcerptId) -> Option<&Excerpt> {
4164        let mut cursor = self.excerpts.cursor::<Option<&Locator>>(&());
4165        let locator = self.excerpt_locator_for_id(excerpt_id);
4166        cursor.seek(&Some(locator), Bias::Left, &());
4167        if let Some(excerpt) = cursor.item() {
4168            if excerpt.id == excerpt_id {
4169                return Some(excerpt);
4170            }
4171        }
4172        None
4173    }
4174
4175    /// Returns the excerpt containing range and its offset start within the multibuffer or none if `range` spans multiple excerpts
4176    pub fn excerpt_containing<T: ToOffset>(&self, range: Range<T>) -> Option<MultiBufferExcerpt> {
4177        let range = range.start.to_offset(self)..range.end.to_offset(self);
4178
4179        let mut cursor = self.excerpts.cursor::<usize>(&());
4180        cursor.seek(&range.start, Bias::Right, &());
4181        let start_excerpt = cursor.item()?;
4182
4183        if range.start == range.end {
4184            return Some(MultiBufferExcerpt::new(start_excerpt, *cursor.start()));
4185        }
4186
4187        cursor.seek(&range.end, Bias::Right, &());
4188        let end_excerpt = cursor.item()?;
4189
4190        if start_excerpt.id == end_excerpt.id {
4191            Some(MultiBufferExcerpt::new(start_excerpt, *cursor.start()))
4192        } else {
4193            None
4194        }
4195    }
4196
4197    // Takes an iterator over anchor ranges and returns a new iterator over anchor ranges that don't
4198    // span across excerpt boundaries.
4199    pub fn split_ranges<'a, I>(&'a self, ranges: I) -> impl Iterator<Item = Range<Anchor>> + 'a
4200    where
4201        I: IntoIterator<Item = Range<Anchor>> + 'a,
4202    {
4203        let mut ranges = ranges.into_iter().map(|range| range.to_offset(self));
4204        let mut cursor = self.excerpts.cursor::<usize>(&());
4205        cursor.next(&());
4206        let mut current_range = ranges.next();
4207        iter::from_fn(move || {
4208            let range = current_range.clone()?;
4209            if range.start >= cursor.end(&()) {
4210                cursor.seek_forward(&range.start, Bias::Right, &());
4211                if range.start == self.len() {
4212                    cursor.prev(&());
4213                }
4214            }
4215
4216            let excerpt = cursor.item()?;
4217            let range_start_in_excerpt = cmp::max(range.start, *cursor.start());
4218            let range_end_in_excerpt = if excerpt.has_trailing_newline {
4219                cmp::min(range.end, cursor.end(&()) - 1)
4220            } else {
4221                cmp::min(range.end, cursor.end(&()))
4222            };
4223            let buffer_range = MultiBufferExcerpt::new(excerpt, *cursor.start())
4224                .map_range_to_buffer(range_start_in_excerpt..range_end_in_excerpt);
4225
4226            let subrange_start_anchor = Anchor {
4227                buffer_id: Some(excerpt.buffer_id),
4228                excerpt_id: excerpt.id,
4229                text_anchor: excerpt.buffer.anchor_before(buffer_range.start),
4230            };
4231            let subrange_end_anchor = Anchor {
4232                buffer_id: Some(excerpt.buffer_id),
4233                excerpt_id: excerpt.id,
4234                text_anchor: excerpt.buffer.anchor_after(buffer_range.end),
4235            };
4236
4237            if range.end > cursor.end(&()) {
4238                cursor.next(&());
4239            } else {
4240                current_range = ranges.next();
4241            }
4242
4243            Some(subrange_start_anchor..subrange_end_anchor)
4244        })
4245    }
4246
4247    /// Returns excerpts overlapping the given ranges. If range spans multiple excerpts returns one range for each excerpt
4248    ///
4249    /// The ranges are specified in the coordinate space of the multibuffer, not the individual excerpted buffers.
4250    /// Each returned excerpt's range is in the coordinate space of its source buffer.
4251    pub fn excerpts_in_ranges(
4252        &self,
4253        ranges: impl IntoIterator<Item = Range<Anchor>>,
4254    ) -> impl Iterator<Item = (ExcerptId, &BufferSnapshot, Range<usize>)> {
4255        let mut ranges = ranges.into_iter().map(|range| range.to_offset(self));
4256        let mut cursor = self.excerpts.cursor::<usize>(&());
4257        cursor.next(&());
4258        let mut current_range = ranges.next();
4259        iter::from_fn(move || {
4260            let range = current_range.clone()?;
4261            if range.start >= cursor.end(&()) {
4262                cursor.seek_forward(&range.start, Bias::Right, &());
4263                if range.start == self.len() {
4264                    cursor.prev(&());
4265                }
4266            }
4267
4268            let excerpt = cursor.item()?;
4269            let range_start_in_excerpt = cmp::max(range.start, *cursor.start());
4270            let range_end_in_excerpt = if excerpt.has_trailing_newline {
4271                cmp::min(range.end, cursor.end(&()) - 1)
4272            } else {
4273                cmp::min(range.end, cursor.end(&()))
4274            };
4275            let buffer_range = MultiBufferExcerpt::new(excerpt, *cursor.start())
4276                .map_range_to_buffer(range_start_in_excerpt..range_end_in_excerpt);
4277
4278            if range.end > cursor.end(&()) {
4279                cursor.next(&());
4280            } else {
4281                current_range = ranges.next();
4282            }
4283
4284            Some((excerpt.id, &excerpt.buffer, buffer_range))
4285        })
4286    }
4287
4288    pub fn selections_in_range<'a>(
4289        &'a self,
4290        range: &'a Range<Anchor>,
4291        include_local: bool,
4292    ) -> impl 'a + Iterator<Item = (ReplicaId, bool, CursorShape, Selection<Anchor>)> {
4293        let mut cursor = self.excerpts.cursor::<ExcerptSummary>(&());
4294        let start_locator = self.excerpt_locator_for_id(range.start.excerpt_id);
4295        let end_locator = self.excerpt_locator_for_id(range.end.excerpt_id);
4296        cursor.seek(start_locator, Bias::Left, &());
4297        cursor
4298            .take_while(move |excerpt| excerpt.locator <= *end_locator)
4299            .flat_map(move |excerpt| {
4300                let mut query_range = excerpt.range.context.start..excerpt.range.context.end;
4301                if excerpt.id == range.start.excerpt_id {
4302                    query_range.start = range.start.text_anchor;
4303                }
4304                if excerpt.id == range.end.excerpt_id {
4305                    query_range.end = range.end.text_anchor;
4306                }
4307
4308                excerpt
4309                    .buffer
4310                    .selections_in_range(query_range, include_local)
4311                    .flat_map(move |(replica_id, line_mode, cursor_shape, selections)| {
4312                        selections.map(move |selection| {
4313                            let mut start = Anchor {
4314                                buffer_id: Some(excerpt.buffer_id),
4315                                excerpt_id: excerpt.id,
4316                                text_anchor: selection.start,
4317                            };
4318                            let mut end = Anchor {
4319                                buffer_id: Some(excerpt.buffer_id),
4320                                excerpt_id: excerpt.id,
4321                                text_anchor: selection.end,
4322                            };
4323                            if range.start.cmp(&start, self).is_gt() {
4324                                start = range.start;
4325                            }
4326                            if range.end.cmp(&end, self).is_lt() {
4327                                end = range.end;
4328                            }
4329
4330                            (
4331                                replica_id,
4332                                line_mode,
4333                                cursor_shape,
4334                                Selection {
4335                                    id: selection.id,
4336                                    start,
4337                                    end,
4338                                    reversed: selection.reversed,
4339                                    goal: selection.goal,
4340                                },
4341                            )
4342                        })
4343                    })
4344            })
4345    }
4346
4347    pub fn show_headers(&self) -> bool {
4348        self.show_headers
4349    }
4350}
4351
4352#[cfg(any(test, feature = "test-support"))]
4353impl MultiBufferSnapshot {
4354    pub fn random_byte_range(&self, start_offset: usize, rng: &mut impl rand::Rng) -> Range<usize> {
4355        let end = self.clip_offset(rng.gen_range(start_offset..=self.len()), Bias::Right);
4356        let start = self.clip_offset(rng.gen_range(start_offset..=end), Bias::Right);
4357        start..end
4358    }
4359}
4360
4361impl History {
4362    fn start_transaction(&mut self, now: Instant) -> Option<TransactionId> {
4363        self.transaction_depth += 1;
4364        if self.transaction_depth == 1 {
4365            let id = self.next_transaction_id.tick();
4366            self.undo_stack.push(Transaction {
4367                id,
4368                buffer_transactions: Default::default(),
4369                first_edit_at: now,
4370                last_edit_at: now,
4371                suppress_grouping: false,
4372            });
4373            Some(id)
4374        } else {
4375            None
4376        }
4377    }
4378
4379    fn end_transaction(
4380        &mut self,
4381        now: Instant,
4382        buffer_transactions: HashMap<BufferId, TransactionId>,
4383    ) -> bool {
4384        assert_ne!(self.transaction_depth, 0);
4385        self.transaction_depth -= 1;
4386        if self.transaction_depth == 0 {
4387            if buffer_transactions.is_empty() {
4388                self.undo_stack.pop();
4389                false
4390            } else {
4391                self.redo_stack.clear();
4392                let transaction = self.undo_stack.last_mut().unwrap();
4393                transaction.last_edit_at = now;
4394                for (buffer_id, transaction_id) in buffer_transactions {
4395                    transaction
4396                        .buffer_transactions
4397                        .entry(buffer_id)
4398                        .or_insert(transaction_id);
4399                }
4400                true
4401            }
4402        } else {
4403            false
4404        }
4405    }
4406
4407    fn push_transaction<'a, T>(
4408        &mut self,
4409        buffer_transactions: T,
4410        now: Instant,
4411        cx: &ModelContext<MultiBuffer>,
4412    ) where
4413        T: IntoIterator<Item = (&'a Model<Buffer>, &'a language::Transaction)>,
4414    {
4415        assert_eq!(self.transaction_depth, 0);
4416        let transaction = Transaction {
4417            id: self.next_transaction_id.tick(),
4418            buffer_transactions: buffer_transactions
4419                .into_iter()
4420                .map(|(buffer, transaction)| (buffer.read(cx).remote_id(), transaction.id))
4421                .collect(),
4422            first_edit_at: now,
4423            last_edit_at: now,
4424            suppress_grouping: false,
4425        };
4426        if !transaction.buffer_transactions.is_empty() {
4427            self.undo_stack.push(transaction);
4428            self.redo_stack.clear();
4429        }
4430    }
4431
4432    fn finalize_last_transaction(&mut self) {
4433        if let Some(transaction) = self.undo_stack.last_mut() {
4434            transaction.suppress_grouping = true;
4435        }
4436    }
4437
4438    fn forget(&mut self, transaction_id: TransactionId) -> Option<Transaction> {
4439        if let Some(ix) = self
4440            .undo_stack
4441            .iter()
4442            .rposition(|transaction| transaction.id == transaction_id)
4443        {
4444            Some(self.undo_stack.remove(ix))
4445        } else if let Some(ix) = self
4446            .redo_stack
4447            .iter()
4448            .rposition(|transaction| transaction.id == transaction_id)
4449        {
4450            Some(self.redo_stack.remove(ix))
4451        } else {
4452            None
4453        }
4454    }
4455
4456    fn transaction(&self, transaction_id: TransactionId) -> Option<&Transaction> {
4457        self.undo_stack
4458            .iter()
4459            .find(|transaction| transaction.id == transaction_id)
4460            .or_else(|| {
4461                self.redo_stack
4462                    .iter()
4463                    .find(|transaction| transaction.id == transaction_id)
4464            })
4465    }
4466
4467    fn transaction_mut(&mut self, transaction_id: TransactionId) -> Option<&mut Transaction> {
4468        self.undo_stack
4469            .iter_mut()
4470            .find(|transaction| transaction.id == transaction_id)
4471            .or_else(|| {
4472                self.redo_stack
4473                    .iter_mut()
4474                    .find(|transaction| transaction.id == transaction_id)
4475            })
4476    }
4477
4478    fn pop_undo(&mut self) -> Option<&mut Transaction> {
4479        assert_eq!(self.transaction_depth, 0);
4480        if let Some(transaction) = self.undo_stack.pop() {
4481            self.redo_stack.push(transaction);
4482            self.redo_stack.last_mut()
4483        } else {
4484            None
4485        }
4486    }
4487
4488    fn pop_redo(&mut self) -> Option<&mut Transaction> {
4489        assert_eq!(self.transaction_depth, 0);
4490        if let Some(transaction) = self.redo_stack.pop() {
4491            self.undo_stack.push(transaction);
4492            self.undo_stack.last_mut()
4493        } else {
4494            None
4495        }
4496    }
4497
4498    fn remove_from_undo(&mut self, transaction_id: TransactionId) -> Option<&Transaction> {
4499        let ix = self
4500            .undo_stack
4501            .iter()
4502            .rposition(|transaction| transaction.id == transaction_id)?;
4503        let transaction = self.undo_stack.remove(ix);
4504        self.redo_stack.push(transaction);
4505        self.redo_stack.last()
4506    }
4507
4508    fn group(&mut self) -> Option<TransactionId> {
4509        let mut count = 0;
4510        let mut transactions = self.undo_stack.iter();
4511        if let Some(mut transaction) = transactions.next_back() {
4512            while let Some(prev_transaction) = transactions.next_back() {
4513                if !prev_transaction.suppress_grouping
4514                    && transaction.first_edit_at - prev_transaction.last_edit_at
4515                        <= self.group_interval
4516                {
4517                    transaction = prev_transaction;
4518                    count += 1;
4519                } else {
4520                    break;
4521                }
4522            }
4523        }
4524        self.group_trailing(count)
4525    }
4526
4527    fn group_until(&mut self, transaction_id: TransactionId) {
4528        let mut count = 0;
4529        for transaction in self.undo_stack.iter().rev() {
4530            if transaction.id == transaction_id {
4531                self.group_trailing(count);
4532                break;
4533            } else if transaction.suppress_grouping {
4534                break;
4535            } else {
4536                count += 1;
4537            }
4538        }
4539    }
4540
4541    fn group_trailing(&mut self, n: usize) -> Option<TransactionId> {
4542        let new_len = self.undo_stack.len() - n;
4543        let (transactions_to_keep, transactions_to_merge) = self.undo_stack.split_at_mut(new_len);
4544        if let Some(last_transaction) = transactions_to_keep.last_mut() {
4545            if let Some(transaction) = transactions_to_merge.last() {
4546                last_transaction.last_edit_at = transaction.last_edit_at;
4547            }
4548            for to_merge in transactions_to_merge {
4549                for (buffer_id, transaction_id) in &to_merge.buffer_transactions {
4550                    last_transaction
4551                        .buffer_transactions
4552                        .entry(*buffer_id)
4553                        .or_insert(*transaction_id);
4554                }
4555            }
4556        }
4557
4558        self.undo_stack.truncate(new_len);
4559        self.undo_stack.last().map(|t| t.id)
4560    }
4561}
4562
4563impl Excerpt {
4564    fn new(
4565        id: ExcerptId,
4566        locator: Locator,
4567        buffer_id: BufferId,
4568        buffer: BufferSnapshot,
4569        range: ExcerptRange<text::Anchor>,
4570        has_trailing_newline: bool,
4571    ) -> Self {
4572        Excerpt {
4573            id,
4574            locator,
4575            max_buffer_row: range.context.end.to_point(&buffer).row,
4576            text_summary: buffer
4577                .text_summary_for_range::<TextSummary, _>(range.context.to_offset(&buffer)),
4578            buffer_id,
4579            buffer,
4580            range,
4581            has_trailing_newline,
4582        }
4583    }
4584
4585    fn chunks_in_range(&self, range: Range<usize>, language_aware: bool) -> ExcerptChunks {
4586        let content_start = self.range.context.start.to_offset(&self.buffer);
4587        let chunks_start = content_start + range.start;
4588        let chunks_end = content_start + cmp::min(range.end, self.text_summary.len);
4589
4590        let footer_height = if self.has_trailing_newline
4591            && range.start <= self.text_summary.len
4592            && range.end > self.text_summary.len
4593        {
4594            1
4595        } else {
4596            0
4597        };
4598
4599        let content_chunks = self.buffer.chunks(chunks_start..chunks_end, language_aware);
4600
4601        ExcerptChunks {
4602            excerpt_id: self.id,
4603            content_chunks,
4604            footer_height,
4605        }
4606    }
4607
4608    fn seek_chunks(&self, excerpt_chunks: &mut ExcerptChunks, range: Range<usize>) {
4609        let content_start = self.range.context.start.to_offset(&self.buffer);
4610        let chunks_start = content_start + range.start;
4611        let chunks_end = content_start + cmp::min(range.end, self.text_summary.len);
4612        excerpt_chunks.content_chunks.seek(chunks_start..chunks_end);
4613        excerpt_chunks.footer_height = if self.has_trailing_newline
4614            && range.start <= self.text_summary.len
4615            && range.end > self.text_summary.len
4616        {
4617            1
4618        } else {
4619            0
4620        };
4621    }
4622
4623    fn bytes_in_range(&self, range: Range<usize>) -> ExcerptBytes {
4624        let content_start = self.range.context.start.to_offset(&self.buffer);
4625        let bytes_start = content_start + range.start;
4626        let bytes_end = content_start + cmp::min(range.end, self.text_summary.len);
4627        let footer_height = if self.has_trailing_newline
4628            && range.start <= self.text_summary.len
4629            && range.end > self.text_summary.len
4630        {
4631            1
4632        } else {
4633            0
4634        };
4635        let content_bytes = self.buffer.bytes_in_range(bytes_start..bytes_end);
4636
4637        ExcerptBytes {
4638            content_bytes,
4639            padding_height: footer_height,
4640            reversed: false,
4641        }
4642    }
4643
4644    fn reversed_bytes_in_range(&self, range: Range<usize>) -> ExcerptBytes {
4645        let content_start = self.range.context.start.to_offset(&self.buffer);
4646        let bytes_start = content_start + range.start;
4647        let bytes_end = content_start + cmp::min(range.end, self.text_summary.len);
4648        let footer_height = if self.has_trailing_newline
4649            && range.start <= self.text_summary.len
4650            && range.end > self.text_summary.len
4651        {
4652            1
4653        } else {
4654            0
4655        };
4656        let content_bytes = self.buffer.reversed_bytes_in_range(bytes_start..bytes_end);
4657
4658        ExcerptBytes {
4659            content_bytes,
4660            padding_height: footer_height,
4661            reversed: true,
4662        }
4663    }
4664
4665    fn clip_anchor(&self, text_anchor: text::Anchor) -> text::Anchor {
4666        if text_anchor
4667            .cmp(&self.range.context.start, &self.buffer)
4668            .is_lt()
4669        {
4670            self.range.context.start
4671        } else if text_anchor
4672            .cmp(&self.range.context.end, &self.buffer)
4673            .is_gt()
4674        {
4675            self.range.context.end
4676        } else {
4677            text_anchor
4678        }
4679    }
4680
4681    fn contains(&self, anchor: &Anchor) -> bool {
4682        Some(self.buffer_id) == anchor.buffer_id
4683            && self
4684                .range
4685                .context
4686                .start
4687                .cmp(&anchor.text_anchor, &self.buffer)
4688                .is_le()
4689            && self
4690                .range
4691                .context
4692                .end
4693                .cmp(&anchor.text_anchor, &self.buffer)
4694                .is_ge()
4695    }
4696
4697    /// The [`Excerpt`]'s start offset in its [`Buffer`]
4698    fn buffer_start_offset(&self) -> usize {
4699        self.range.context.start.to_offset(&self.buffer)
4700    }
4701
4702    /// The [`Excerpt`]'s end offset in its [`Buffer`]
4703    fn buffer_end_offset(&self) -> usize {
4704        self.buffer_start_offset() + self.text_summary.len
4705    }
4706}
4707
4708impl<'a> MultiBufferExcerpt<'a> {
4709    fn new(excerpt: &'a Excerpt, excerpt_offset: usize) -> Self {
4710        MultiBufferExcerpt {
4711            excerpt,
4712            excerpt_offset,
4713        }
4714    }
4715
4716    pub fn id(&self) -> ExcerptId {
4717        self.excerpt.id
4718    }
4719
4720    pub fn start_anchor(&self) -> Anchor {
4721        Anchor {
4722            buffer_id: Some(self.excerpt.buffer_id),
4723            excerpt_id: self.excerpt.id,
4724            text_anchor: self.excerpt.range.context.start,
4725        }
4726    }
4727
4728    pub fn end_anchor(&self) -> Anchor {
4729        Anchor {
4730            buffer_id: Some(self.excerpt.buffer_id),
4731            excerpt_id: self.excerpt.id,
4732            text_anchor: self.excerpt.range.context.end,
4733        }
4734    }
4735
4736    pub fn buffer(&self) -> &'a BufferSnapshot {
4737        &self.excerpt.buffer
4738    }
4739
4740    /// Maps an offset within the [`MultiBuffer`] to an offset within the [`Buffer`]
4741    pub fn map_offset_to_buffer(&self, offset: usize) -> usize {
4742        self.excerpt.buffer_start_offset() + offset.saturating_sub(self.excerpt_offset)
4743    }
4744
4745    /// Maps a range within the [`MultiBuffer`] to a range within the [`Buffer`]
4746    pub fn map_range_to_buffer(&self, range: Range<usize>) -> Range<usize> {
4747        self.map_offset_to_buffer(range.start)..self.map_offset_to_buffer(range.end)
4748    }
4749
4750    /// Map an offset within the [`Buffer`] to an offset within the [`MultiBuffer`]
4751    pub fn map_offset_from_buffer(&self, buffer_offset: usize) -> usize {
4752        let mut buffer_offset_in_excerpt =
4753            buffer_offset.saturating_sub(self.excerpt.buffer_start_offset());
4754        buffer_offset_in_excerpt =
4755            cmp::min(buffer_offset_in_excerpt, self.excerpt.text_summary.len);
4756
4757        self.excerpt_offset + buffer_offset_in_excerpt
4758    }
4759
4760    /// Map a range within the [`Buffer`] to a range within the [`MultiBuffer`]
4761    pub fn map_range_from_buffer(&self, buffer_range: Range<usize>) -> Range<usize> {
4762        self.map_offset_from_buffer(buffer_range.start)
4763            ..self.map_offset_from_buffer(buffer_range.end)
4764    }
4765
4766    /// Returns true if the entirety of the given range is in the buffer's excerpt
4767    pub fn contains_buffer_range(&self, range: Range<usize>) -> bool {
4768        range.start >= self.excerpt.buffer_start_offset()
4769            && range.end <= self.excerpt.buffer_end_offset()
4770    }
4771}
4772
4773impl ExcerptId {
4774    pub fn min() -> Self {
4775        Self(0)
4776    }
4777
4778    pub fn max() -> Self {
4779        Self(usize::MAX)
4780    }
4781
4782    pub fn to_proto(&self) -> u64 {
4783        self.0 as _
4784    }
4785
4786    pub fn from_proto(proto: u64) -> Self {
4787        Self(proto as _)
4788    }
4789
4790    pub fn cmp(&self, other: &Self, snapshot: &MultiBufferSnapshot) -> cmp::Ordering {
4791        let a = snapshot.excerpt_locator_for_id(*self);
4792        let b = snapshot.excerpt_locator_for_id(*other);
4793        a.cmp(b).then_with(|| self.0.cmp(&other.0))
4794    }
4795}
4796
4797impl From<ExcerptId> for usize {
4798    fn from(val: ExcerptId) -> Self {
4799        val.0
4800    }
4801}
4802
4803impl fmt::Debug for Excerpt {
4804    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
4805        f.debug_struct("Excerpt")
4806            .field("id", &self.id)
4807            .field("locator", &self.locator)
4808            .field("buffer_id", &self.buffer_id)
4809            .field("range", &self.range)
4810            .field("text_summary", &self.text_summary)
4811            .field("has_trailing_newline", &self.has_trailing_newline)
4812            .finish()
4813    }
4814}
4815
4816impl sum_tree::Item for Excerpt {
4817    type Summary = ExcerptSummary;
4818
4819    fn summary(&self, _cx: &()) -> Self::Summary {
4820        let mut text = self.text_summary.clone();
4821        if self.has_trailing_newline {
4822            text += TextSummary::from("\n");
4823        }
4824        ExcerptSummary {
4825            excerpt_id: self.id,
4826            excerpt_locator: self.locator.clone(),
4827            max_buffer_row: MultiBufferRow(self.max_buffer_row),
4828            text,
4829        }
4830    }
4831}
4832
4833impl sum_tree::Item for ExcerptIdMapping {
4834    type Summary = ExcerptId;
4835
4836    fn summary(&self, _cx: &()) -> Self::Summary {
4837        self.id
4838    }
4839}
4840
4841impl sum_tree::KeyedItem for ExcerptIdMapping {
4842    type Key = ExcerptId;
4843
4844    fn key(&self) -> Self::Key {
4845        self.id
4846    }
4847}
4848
4849impl sum_tree::Summary for ExcerptId {
4850    type Context = ();
4851
4852    fn zero(_cx: &()) -> Self {
4853        Default::default()
4854    }
4855
4856    fn add_summary(&mut self, other: &Self, _: &()) {
4857        *self = *other;
4858    }
4859}
4860
4861impl sum_tree::Summary for ExcerptSummary {
4862    type Context = ();
4863
4864    fn zero(_cx: &()) -> Self {
4865        Default::default()
4866    }
4867
4868    fn add_summary(&mut self, summary: &Self, _: &()) {
4869        debug_assert!(summary.excerpt_locator > self.excerpt_locator);
4870        self.excerpt_locator = summary.excerpt_locator.clone();
4871        self.text.add_summary(&summary.text, &());
4872        self.max_buffer_row = cmp::max(self.max_buffer_row, summary.max_buffer_row);
4873    }
4874}
4875
4876impl<'a> sum_tree::Dimension<'a, ExcerptSummary> for TextSummary {
4877    fn zero(_cx: &()) -> Self {
4878        Default::default()
4879    }
4880
4881    fn add_summary(&mut self, summary: &'a ExcerptSummary, _: &()) {
4882        *self += &summary.text;
4883    }
4884}
4885
4886impl<'a> sum_tree::Dimension<'a, ExcerptSummary> for usize {
4887    fn zero(_cx: &()) -> Self {
4888        Default::default()
4889    }
4890
4891    fn add_summary(&mut self, summary: &'a ExcerptSummary, _: &()) {
4892        *self += summary.text.len;
4893    }
4894}
4895
4896impl<'a> sum_tree::SeekTarget<'a, ExcerptSummary, ExcerptSummary> for usize {
4897    fn cmp(&self, cursor_location: &ExcerptSummary, _: &()) -> cmp::Ordering {
4898        Ord::cmp(self, &cursor_location.text.len)
4899    }
4900}
4901
4902impl<'a> sum_tree::SeekTarget<'a, ExcerptSummary, TextSummary> for Point {
4903    fn cmp(&self, cursor_location: &TextSummary, _: &()) -> cmp::Ordering {
4904        Ord::cmp(self, &cursor_location.lines)
4905    }
4906}
4907
4908impl<'a> sum_tree::SeekTarget<'a, ExcerptSummary, Option<&'a Locator>> for Locator {
4909    fn cmp(&self, cursor_location: &Option<&'a Locator>, _: &()) -> cmp::Ordering {
4910        Ord::cmp(&Some(self), cursor_location)
4911    }
4912}
4913
4914impl<'a> sum_tree::SeekTarget<'a, ExcerptSummary, ExcerptSummary> for Locator {
4915    fn cmp(&self, cursor_location: &ExcerptSummary, _: &()) -> cmp::Ordering {
4916        Ord::cmp(self, &cursor_location.excerpt_locator)
4917    }
4918}
4919
4920impl<'a> sum_tree::Dimension<'a, ExcerptSummary> for OffsetUtf16 {
4921    fn zero(_cx: &()) -> Self {
4922        Default::default()
4923    }
4924
4925    fn add_summary(&mut self, summary: &'a ExcerptSummary, _: &()) {
4926        *self += summary.text.len_utf16;
4927    }
4928}
4929
4930impl<'a> sum_tree::Dimension<'a, ExcerptSummary> for Point {
4931    fn zero(_cx: &()) -> Self {
4932        Default::default()
4933    }
4934
4935    fn add_summary(&mut self, summary: &'a ExcerptSummary, _: &()) {
4936        *self += summary.text.lines;
4937    }
4938}
4939
4940impl<'a> sum_tree::Dimension<'a, ExcerptSummary> for PointUtf16 {
4941    fn zero(_cx: &()) -> Self {
4942        Default::default()
4943    }
4944
4945    fn add_summary(&mut self, summary: &'a ExcerptSummary, _: &()) {
4946        *self += summary.text.lines_utf16()
4947    }
4948}
4949
4950impl<'a> sum_tree::Dimension<'a, ExcerptSummary> for Option<&'a Locator> {
4951    fn zero(_cx: &()) -> Self {
4952        Default::default()
4953    }
4954
4955    fn add_summary(&mut self, summary: &'a ExcerptSummary, _: &()) {
4956        *self = Some(&summary.excerpt_locator);
4957    }
4958}
4959
4960impl<'a> sum_tree::Dimension<'a, ExcerptSummary> for Option<ExcerptId> {
4961    fn zero(_cx: &()) -> Self {
4962        Default::default()
4963    }
4964
4965    fn add_summary(&mut self, summary: &'a ExcerptSummary, _: &()) {
4966        *self = Some(summary.excerpt_id);
4967    }
4968}
4969
4970impl<'a> MultiBufferRows<'a> {
4971    pub fn seek(&mut self, row: MultiBufferRow) {
4972        self.buffer_row_range = 0..0;
4973
4974        self.excerpts
4975            .seek_forward(&Point::new(row.0, 0), Bias::Right, &());
4976        if self.excerpts.item().is_none() {
4977            self.excerpts.prev(&());
4978
4979            if self.excerpts.item().is_none() && row.0 == 0 {
4980                self.buffer_row_range = 0..1;
4981                return;
4982            }
4983        }
4984
4985        if let Some(excerpt) = self.excerpts.item() {
4986            let overshoot = row.0 - self.excerpts.start().row;
4987            let excerpt_start = excerpt.range.context.start.to_point(&excerpt.buffer).row;
4988            self.buffer_row_range.start = excerpt_start + overshoot;
4989            self.buffer_row_range.end = excerpt_start + excerpt.text_summary.lines.row + 1;
4990        }
4991    }
4992}
4993
4994impl<'a> Iterator for MultiBufferRows<'a> {
4995    type Item = Option<u32>;
4996
4997    fn next(&mut self) -> Option<Self::Item> {
4998        loop {
4999            if !self.buffer_row_range.is_empty() {
5000                let row = Some(self.buffer_row_range.start);
5001                self.buffer_row_range.start += 1;
5002                return Some(row);
5003            }
5004            self.excerpts.item()?;
5005            self.excerpts.next(&());
5006            let excerpt = self.excerpts.item()?;
5007            self.buffer_row_range.start = excerpt.range.context.start.to_point(&excerpt.buffer).row;
5008            self.buffer_row_range.end =
5009                self.buffer_row_range.start + excerpt.text_summary.lines.row + 1;
5010        }
5011    }
5012}
5013
5014impl<'a> MultiBufferChunks<'a> {
5015    pub fn offset(&self) -> usize {
5016        self.range.start
5017    }
5018
5019    pub fn seek(&mut self, new_range: Range<usize>) {
5020        self.range = new_range.clone();
5021        self.excerpts.seek(&new_range.start, Bias::Right, &());
5022        if let Some(excerpt) = self.excerpts.item() {
5023            let excerpt_start = self.excerpts.start();
5024            if let Some(excerpt_chunks) = self
5025                .excerpt_chunks
5026                .as_mut()
5027                .filter(|chunks| excerpt.id == chunks.excerpt_id)
5028            {
5029                excerpt.seek_chunks(
5030                    excerpt_chunks,
5031                    self.range.start - excerpt_start..self.range.end - excerpt_start,
5032                );
5033            } else {
5034                self.excerpt_chunks = Some(excerpt.chunks_in_range(
5035                    self.range.start - excerpt_start..self.range.end - excerpt_start,
5036                    self.language_aware,
5037                ));
5038            }
5039        } else {
5040            self.excerpt_chunks = None;
5041        }
5042    }
5043}
5044
5045impl<'a> Iterator for MultiBufferChunks<'a> {
5046    type Item = Chunk<'a>;
5047
5048    fn next(&mut self) -> Option<Self::Item> {
5049        if self.range.is_empty() {
5050            None
5051        } else if let Some(chunk) = self.excerpt_chunks.as_mut()?.next() {
5052            self.range.start += chunk.text.len();
5053            Some(chunk)
5054        } else {
5055            self.excerpts.next(&());
5056            let excerpt = self.excerpts.item()?;
5057            self.excerpt_chunks = Some(excerpt.chunks_in_range(
5058                0..self.range.end - self.excerpts.start(),
5059                self.language_aware,
5060            ));
5061            self.next()
5062        }
5063    }
5064}
5065
5066impl<'a> MultiBufferBytes<'a> {
5067    fn consume(&mut self, len: usize) {
5068        self.range.start += len;
5069        self.chunk = &self.chunk[len..];
5070
5071        if !self.range.is_empty() && self.chunk.is_empty() {
5072            if let Some(chunk) = self.excerpt_bytes.as_mut().and_then(|bytes| bytes.next()) {
5073                self.chunk = chunk;
5074            } else {
5075                self.excerpts.next(&());
5076                if let Some(excerpt) = self.excerpts.item() {
5077                    let mut excerpt_bytes =
5078                        excerpt.bytes_in_range(0..self.range.end - self.excerpts.start());
5079                    self.chunk = excerpt_bytes.next().unwrap();
5080                    self.excerpt_bytes = Some(excerpt_bytes);
5081                }
5082            }
5083        }
5084    }
5085}
5086
5087impl<'a> Iterator for MultiBufferBytes<'a> {
5088    type Item = &'a [u8];
5089
5090    fn next(&mut self) -> Option<Self::Item> {
5091        let chunk = self.chunk;
5092        if chunk.is_empty() {
5093            None
5094        } else {
5095            self.consume(chunk.len());
5096            Some(chunk)
5097        }
5098    }
5099}
5100
5101impl<'a> io::Read for MultiBufferBytes<'a> {
5102    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
5103        let len = cmp::min(buf.len(), self.chunk.len());
5104        buf[..len].copy_from_slice(&self.chunk[..len]);
5105        if len > 0 {
5106            self.consume(len);
5107        }
5108        Ok(len)
5109    }
5110}
5111
5112impl<'a> ReversedMultiBufferBytes<'a> {
5113    fn consume(&mut self, len: usize) {
5114        self.range.end -= len;
5115        self.chunk = &self.chunk[..self.chunk.len() - len];
5116
5117        if !self.range.is_empty() && self.chunk.is_empty() {
5118            if let Some(chunk) = self.excerpt_bytes.as_mut().and_then(|bytes| bytes.next()) {
5119                self.chunk = chunk;
5120            } else {
5121                self.excerpts.prev(&());
5122                if let Some(excerpt) = self.excerpts.item() {
5123                    let mut excerpt_bytes = excerpt.reversed_bytes_in_range(
5124                        self.range.start.saturating_sub(*self.excerpts.start())..usize::MAX,
5125                    );
5126                    self.chunk = excerpt_bytes.next().unwrap();
5127                    self.excerpt_bytes = Some(excerpt_bytes);
5128                }
5129            }
5130        }
5131    }
5132}
5133
5134impl<'a> io::Read for ReversedMultiBufferBytes<'a> {
5135    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
5136        let len = cmp::min(buf.len(), self.chunk.len());
5137        buf[..len].copy_from_slice(&self.chunk[..len]);
5138        buf[..len].reverse();
5139        if len > 0 {
5140            self.consume(len);
5141        }
5142        Ok(len)
5143    }
5144}
5145impl<'a> Iterator for ExcerptBytes<'a> {
5146    type Item = &'a [u8];
5147
5148    fn next(&mut self) -> Option<Self::Item> {
5149        if self.reversed && self.padding_height > 0 {
5150            let result = &NEWLINES[..self.padding_height];
5151            self.padding_height = 0;
5152            return Some(result);
5153        }
5154
5155        if let Some(chunk) = self.content_bytes.next() {
5156            if !chunk.is_empty() {
5157                return Some(chunk);
5158            }
5159        }
5160
5161        if self.padding_height > 0 {
5162            let result = &NEWLINES[..self.padding_height];
5163            self.padding_height = 0;
5164            return Some(result);
5165        }
5166
5167        None
5168    }
5169}
5170
5171impl<'a> Iterator for ExcerptChunks<'a> {
5172    type Item = Chunk<'a>;
5173
5174    fn next(&mut self) -> Option<Self::Item> {
5175        if let Some(chunk) = self.content_chunks.next() {
5176            return Some(chunk);
5177        }
5178
5179        if self.footer_height > 0 {
5180            let text = unsafe { str::from_utf8_unchecked(&NEWLINES[..self.footer_height]) };
5181            self.footer_height = 0;
5182            return Some(Chunk {
5183                text,
5184                ..Default::default()
5185            });
5186        }
5187
5188        None
5189    }
5190}
5191
5192impl ToOffset for Point {
5193    fn to_offset<'a>(&self, snapshot: &MultiBufferSnapshot) -> usize {
5194        snapshot.point_to_offset(*self)
5195    }
5196}
5197
5198impl ToOffset for usize {
5199    fn to_offset<'a>(&self, snapshot: &MultiBufferSnapshot) -> usize {
5200        assert!(*self <= snapshot.len(), "offset is out of range");
5201        *self
5202    }
5203}
5204
5205impl ToOffset for OffsetUtf16 {
5206    fn to_offset<'a>(&self, snapshot: &MultiBufferSnapshot) -> usize {
5207        snapshot.offset_utf16_to_offset(*self)
5208    }
5209}
5210
5211impl ToOffset for PointUtf16 {
5212    fn to_offset<'a>(&self, snapshot: &MultiBufferSnapshot) -> usize {
5213        snapshot.point_utf16_to_offset(*self)
5214    }
5215}
5216
5217impl ToOffsetUtf16 for OffsetUtf16 {
5218    fn to_offset_utf16(&self, _snapshot: &MultiBufferSnapshot) -> OffsetUtf16 {
5219        *self
5220    }
5221}
5222
5223impl ToOffsetUtf16 for usize {
5224    fn to_offset_utf16(&self, snapshot: &MultiBufferSnapshot) -> OffsetUtf16 {
5225        snapshot.offset_to_offset_utf16(*self)
5226    }
5227}
5228
5229impl ToPoint for usize {
5230    fn to_point<'a>(&self, snapshot: &MultiBufferSnapshot) -> Point {
5231        snapshot.offset_to_point(*self)
5232    }
5233}
5234
5235impl ToPoint for Point {
5236    fn to_point<'a>(&self, _: &MultiBufferSnapshot) -> Point {
5237        *self
5238    }
5239}
5240
5241impl ToPointUtf16 for usize {
5242    fn to_point_utf16<'a>(&self, snapshot: &MultiBufferSnapshot) -> PointUtf16 {
5243        snapshot.offset_to_point_utf16(*self)
5244    }
5245}
5246
5247impl ToPointUtf16 for Point {
5248    fn to_point_utf16<'a>(&self, snapshot: &MultiBufferSnapshot) -> PointUtf16 {
5249        snapshot.point_to_point_utf16(*self)
5250    }
5251}
5252
5253impl ToPointUtf16 for PointUtf16 {
5254    fn to_point_utf16<'a>(&self, _: &MultiBufferSnapshot) -> PointUtf16 {
5255        *self
5256    }
5257}
5258
5259pub fn build_excerpt_ranges<T>(
5260    buffer: &BufferSnapshot,
5261    ranges: &[Range<T>],
5262    context_line_count: u32,
5263) -> (Vec<ExcerptRange<Point>>, Vec<usize>)
5264where
5265    T: text::ToPoint,
5266{
5267    let max_point = buffer.max_point();
5268    let mut range_counts = Vec::new();
5269    let mut excerpt_ranges = Vec::new();
5270    let mut range_iter = ranges
5271        .iter()
5272        .map(|range| range.start.to_point(buffer)..range.end.to_point(buffer))
5273        .peekable();
5274    while let Some(range) = range_iter.next() {
5275        let excerpt_start = Point::new(range.start.row.saturating_sub(context_line_count), 0);
5276        let row = (range.end.row + context_line_count).min(max_point.row);
5277        let mut excerpt_end = Point::new(row, buffer.line_len(row));
5278
5279        let mut ranges_in_excerpt = 1;
5280
5281        while let Some(next_range) = range_iter.peek() {
5282            if next_range.start.row <= excerpt_end.row + context_line_count {
5283                let row = (next_range.end.row + context_line_count).min(max_point.row);
5284                excerpt_end = Point::new(row, buffer.line_len(row));
5285
5286                ranges_in_excerpt += 1;
5287                range_iter.next();
5288            } else {
5289                break;
5290            }
5291        }
5292
5293        excerpt_ranges.push(ExcerptRange {
5294            context: excerpt_start..excerpt_end,
5295            primary: Some(range),
5296        });
5297        range_counts.push(ranges_in_excerpt);
5298    }
5299
5300    (excerpt_ranges, range_counts)
5301}
5302
5303#[cfg(test)]
5304mod tests {
5305    use super::*;
5306    use gpui::{AppContext, Context, TestAppContext};
5307    use language::{Buffer, Rope};
5308    use parking_lot::RwLock;
5309    use rand::prelude::*;
5310    use settings::SettingsStore;
5311    use std::env;
5312    use util::test::sample_text;
5313
5314    #[ctor::ctor]
5315    fn init_logger() {
5316        if std::env::var("RUST_LOG").is_ok() {
5317            env_logger::init();
5318        }
5319    }
5320
5321    #[gpui::test]
5322    fn test_singleton(cx: &mut AppContext) {
5323        let buffer = cx.new_model(|cx| Buffer::local(sample_text(6, 6, 'a'), cx));
5324        let multibuffer = cx.new_model(|cx| MultiBuffer::singleton(buffer.clone(), cx));
5325
5326        let snapshot = multibuffer.read(cx).snapshot(cx);
5327        assert_eq!(snapshot.text(), buffer.read(cx).text());
5328
5329        assert_eq!(
5330            snapshot.buffer_rows(MultiBufferRow(0)).collect::<Vec<_>>(),
5331            (0..buffer.read(cx).row_count())
5332                .map(Some)
5333                .collect::<Vec<_>>()
5334        );
5335
5336        buffer.update(cx, |buffer, cx| buffer.edit([(1..3, "XXX\n")], None, cx));
5337        let snapshot = multibuffer.read(cx).snapshot(cx);
5338
5339        assert_eq!(snapshot.text(), buffer.read(cx).text());
5340        assert_eq!(
5341            snapshot.buffer_rows(MultiBufferRow(0)).collect::<Vec<_>>(),
5342            (0..buffer.read(cx).row_count())
5343                .map(Some)
5344                .collect::<Vec<_>>()
5345        );
5346    }
5347
5348    #[gpui::test]
5349    fn test_remote(cx: &mut AppContext) {
5350        let host_buffer = cx.new_model(|cx| Buffer::local("a", cx));
5351        let guest_buffer = cx.new_model(|cx| {
5352            let state = host_buffer.read(cx).to_proto(cx);
5353            let ops = cx
5354                .background_executor()
5355                .block(host_buffer.read(cx).serialize_ops(None, cx));
5356            let mut buffer = Buffer::from_proto(1, Capability::ReadWrite, state, None).unwrap();
5357            buffer.apply_ops(
5358                ops.into_iter()
5359                    .map(|op| language::proto::deserialize_operation(op).unwrap()),
5360                cx,
5361            );
5362            buffer
5363        });
5364        let multibuffer = cx.new_model(|cx| MultiBuffer::singleton(guest_buffer.clone(), cx));
5365        let snapshot = multibuffer.read(cx).snapshot(cx);
5366        assert_eq!(snapshot.text(), "a");
5367
5368        guest_buffer.update(cx, |buffer, cx| buffer.edit([(1..1, "b")], None, cx));
5369        let snapshot = multibuffer.read(cx).snapshot(cx);
5370        assert_eq!(snapshot.text(), "ab");
5371
5372        guest_buffer.update(cx, |buffer, cx| buffer.edit([(2..2, "c")], None, cx));
5373        let snapshot = multibuffer.read(cx).snapshot(cx);
5374        assert_eq!(snapshot.text(), "abc");
5375    }
5376
5377    #[gpui::test]
5378    fn test_excerpt_boundaries_and_clipping(cx: &mut AppContext) {
5379        let buffer_1 = cx.new_model(|cx| Buffer::local(sample_text(6, 6, 'a'), cx));
5380        let buffer_2 = cx.new_model(|cx| Buffer::local(sample_text(6, 6, 'g'), cx));
5381        let multibuffer = cx.new_model(|_| MultiBuffer::new(Capability::ReadWrite));
5382
5383        let events = Arc::new(RwLock::new(Vec::<Event>::new()));
5384        multibuffer.update(cx, |_, cx| {
5385            let events = events.clone();
5386            cx.subscribe(&multibuffer, move |_, _, event, _| {
5387                if let Event::Edited { .. } = event {
5388                    events.write().push(event.clone())
5389                }
5390            })
5391            .detach();
5392        });
5393
5394        let subscription = multibuffer.update(cx, |multibuffer, cx| {
5395            let subscription = multibuffer.subscribe();
5396            multibuffer.push_excerpts(
5397                buffer_1.clone(),
5398                [ExcerptRange {
5399                    context: Point::new(1, 2)..Point::new(2, 5),
5400                    primary: None,
5401                }],
5402                cx,
5403            );
5404            assert_eq!(
5405                subscription.consume().into_inner(),
5406                [Edit {
5407                    old: 0..0,
5408                    new: 0..10
5409                }]
5410            );
5411
5412            multibuffer.push_excerpts(
5413                buffer_1.clone(),
5414                [ExcerptRange {
5415                    context: Point::new(3, 3)..Point::new(4, 4),
5416                    primary: None,
5417                }],
5418                cx,
5419            );
5420            multibuffer.push_excerpts(
5421                buffer_2.clone(),
5422                [ExcerptRange {
5423                    context: Point::new(3, 1)..Point::new(3, 3),
5424                    primary: None,
5425                }],
5426                cx,
5427            );
5428            assert_eq!(
5429                subscription.consume().into_inner(),
5430                [Edit {
5431                    old: 10..10,
5432                    new: 10..22
5433                }]
5434            );
5435
5436            subscription
5437        });
5438
5439        // Adding excerpts emits an edited event.
5440        assert_eq!(
5441            events.read().as_slice(),
5442            &[
5443                Event::Edited {
5444                    singleton_buffer_edited: false
5445                },
5446                Event::Edited {
5447                    singleton_buffer_edited: false
5448                },
5449                Event::Edited {
5450                    singleton_buffer_edited: false
5451                }
5452            ]
5453        );
5454
5455        let snapshot = multibuffer.read(cx).snapshot(cx);
5456        assert_eq!(
5457            snapshot.text(),
5458            concat!(
5459                "bbbb\n",  // Preserve newlines
5460                "ccccc\n", //
5461                "ddd\n",   //
5462                "eeee\n",  //
5463                "jj"       //
5464            )
5465        );
5466        assert_eq!(
5467            snapshot.buffer_rows(MultiBufferRow(0)).collect::<Vec<_>>(),
5468            [Some(1), Some(2), Some(3), Some(4), Some(3)]
5469        );
5470        assert_eq!(
5471            snapshot.buffer_rows(MultiBufferRow(2)).collect::<Vec<_>>(),
5472            [Some(3), Some(4), Some(3)]
5473        );
5474        assert_eq!(
5475            snapshot.buffer_rows(MultiBufferRow(4)).collect::<Vec<_>>(),
5476            [Some(3)]
5477        );
5478        assert_eq!(
5479            snapshot.buffer_rows(MultiBufferRow(5)).collect::<Vec<_>>(),
5480            []
5481        );
5482
5483        assert_eq!(
5484            boundaries_in_range(Point::new(0, 0)..Point::new(4, 2), &snapshot),
5485            &[
5486                (MultiBufferRow(0), "bbbb\nccccc".to_string(), true),
5487                (MultiBufferRow(2), "ddd\neeee".to_string(), false),
5488                (MultiBufferRow(4), "jj".to_string(), true),
5489            ]
5490        );
5491        assert_eq!(
5492            boundaries_in_range(Point::new(0, 0)..Point::new(2, 0), &snapshot),
5493            &[(MultiBufferRow(0), "bbbb\nccccc".to_string(), true)]
5494        );
5495        assert_eq!(
5496            boundaries_in_range(Point::new(1, 0)..Point::new(1, 5), &snapshot),
5497            &[]
5498        );
5499        assert_eq!(
5500            boundaries_in_range(Point::new(1, 0)..Point::new(2, 0), &snapshot),
5501            &[]
5502        );
5503        assert_eq!(
5504            boundaries_in_range(Point::new(1, 0)..Point::new(4, 0), &snapshot),
5505            &[(MultiBufferRow(2), "ddd\neeee".to_string(), false)]
5506        );
5507        assert_eq!(
5508            boundaries_in_range(Point::new(1, 0)..Point::new(4, 0), &snapshot),
5509            &[(MultiBufferRow(2), "ddd\neeee".to_string(), false)]
5510        );
5511        assert_eq!(
5512            boundaries_in_range(Point::new(2, 0)..Point::new(3, 0), &snapshot),
5513            &[(MultiBufferRow(2), "ddd\neeee".to_string(), false)]
5514        );
5515        assert_eq!(
5516            boundaries_in_range(Point::new(4, 0)..Point::new(4, 2), &snapshot),
5517            &[(MultiBufferRow(4), "jj".to_string(), true)]
5518        );
5519        assert_eq!(
5520            boundaries_in_range(Point::new(4, 2)..Point::new(4, 2), &snapshot),
5521            &[]
5522        );
5523
5524        buffer_1.update(cx, |buffer, cx| {
5525            let text = "\n";
5526            buffer.edit(
5527                [
5528                    (Point::new(0, 0)..Point::new(0, 0), text),
5529                    (Point::new(2, 1)..Point::new(2, 3), text),
5530                ],
5531                None,
5532                cx,
5533            );
5534        });
5535
5536        let snapshot = multibuffer.read(cx).snapshot(cx);
5537        assert_eq!(
5538            snapshot.text(),
5539            concat!(
5540                "bbbb\n", // Preserve newlines
5541                "c\n",    //
5542                "cc\n",   //
5543                "ddd\n",  //
5544                "eeee\n", //
5545                "jj"      //
5546            )
5547        );
5548
5549        assert_eq!(
5550            subscription.consume().into_inner(),
5551            [Edit {
5552                old: 6..8,
5553                new: 6..7
5554            }]
5555        );
5556
5557        let snapshot = multibuffer.read(cx).snapshot(cx);
5558        assert_eq!(
5559            snapshot.clip_point(Point::new(0, 5), Bias::Left),
5560            Point::new(0, 4)
5561        );
5562        assert_eq!(
5563            snapshot.clip_point(Point::new(0, 5), Bias::Right),
5564            Point::new(0, 4)
5565        );
5566        assert_eq!(
5567            snapshot.clip_point(Point::new(5, 1), Bias::Right),
5568            Point::new(5, 1)
5569        );
5570        assert_eq!(
5571            snapshot.clip_point(Point::new(5, 2), Bias::Right),
5572            Point::new(5, 2)
5573        );
5574        assert_eq!(
5575            snapshot.clip_point(Point::new(5, 3), Bias::Right),
5576            Point::new(5, 2)
5577        );
5578
5579        let snapshot = multibuffer.update(cx, |multibuffer, cx| {
5580            let (buffer_2_excerpt_id, _) =
5581                multibuffer.excerpts_for_buffer(&buffer_2, cx)[0].clone();
5582            multibuffer.remove_excerpts([buffer_2_excerpt_id], cx);
5583            multibuffer.snapshot(cx)
5584        });
5585
5586        assert_eq!(
5587            snapshot.text(),
5588            concat!(
5589                "bbbb\n", // Preserve newlines
5590                "c\n",    //
5591                "cc\n",   //
5592                "ddd\n",  //
5593                "eeee",   //
5594            )
5595        );
5596
5597        fn boundaries_in_range(
5598            range: Range<Point>,
5599            snapshot: &MultiBufferSnapshot,
5600        ) -> Vec<(MultiBufferRow, String, bool)> {
5601            snapshot
5602                .excerpt_boundaries_in_range(range)
5603                .filter_map(|boundary| {
5604                    let starts_new_buffer = boundary.starts_new_buffer();
5605                    boundary.next.map(|next| {
5606                        (
5607                            boundary.row,
5608                            next.buffer
5609                                .text_for_range(next.range.context)
5610                                .collect::<String>(),
5611                            starts_new_buffer,
5612                        )
5613                    })
5614                })
5615                .collect::<Vec<_>>()
5616        }
5617    }
5618
5619    #[gpui::test]
5620    fn test_excerpt_events(cx: &mut AppContext) {
5621        let buffer_1 = cx.new_model(|cx| Buffer::local(sample_text(10, 3, 'a'), cx));
5622        let buffer_2 = cx.new_model(|cx| Buffer::local(sample_text(10, 3, 'm'), cx));
5623
5624        let leader_multibuffer = cx.new_model(|_| MultiBuffer::new(Capability::ReadWrite));
5625        let follower_multibuffer = cx.new_model(|_| MultiBuffer::new(Capability::ReadWrite));
5626        let follower_edit_event_count = Arc::new(RwLock::new(0));
5627
5628        follower_multibuffer.update(cx, |_, cx| {
5629            let follower_edit_event_count = follower_edit_event_count.clone();
5630            cx.subscribe(
5631                &leader_multibuffer,
5632                move |follower, _, event, cx| match event.clone() {
5633                    Event::ExcerptsAdded {
5634                        buffer,
5635                        predecessor,
5636                        excerpts,
5637                    } => follower.insert_excerpts_with_ids_after(predecessor, buffer, excerpts, cx),
5638                    Event::ExcerptsRemoved { ids } => follower.remove_excerpts(ids, cx),
5639                    Event::Edited { .. } => {
5640                        *follower_edit_event_count.write() += 1;
5641                    }
5642                    _ => {}
5643                },
5644            )
5645            .detach();
5646        });
5647
5648        leader_multibuffer.update(cx, |leader, cx| {
5649            leader.push_excerpts(
5650                buffer_1.clone(),
5651                [
5652                    ExcerptRange {
5653                        context: 0..8,
5654                        primary: None,
5655                    },
5656                    ExcerptRange {
5657                        context: 12..16,
5658                        primary: None,
5659                    },
5660                ],
5661                cx,
5662            );
5663            leader.insert_excerpts_after(
5664                leader.excerpt_ids()[0],
5665                buffer_2.clone(),
5666                [
5667                    ExcerptRange {
5668                        context: 0..5,
5669                        primary: None,
5670                    },
5671                    ExcerptRange {
5672                        context: 10..15,
5673                        primary: None,
5674                    },
5675                ],
5676                cx,
5677            )
5678        });
5679        assert_eq!(
5680            leader_multibuffer.read(cx).snapshot(cx).text(),
5681            follower_multibuffer.read(cx).snapshot(cx).text(),
5682        );
5683        assert_eq!(*follower_edit_event_count.read(), 2);
5684
5685        leader_multibuffer.update(cx, |leader, cx| {
5686            let excerpt_ids = leader.excerpt_ids();
5687            leader.remove_excerpts([excerpt_ids[1], excerpt_ids[3]], cx);
5688        });
5689        assert_eq!(
5690            leader_multibuffer.read(cx).snapshot(cx).text(),
5691            follower_multibuffer.read(cx).snapshot(cx).text(),
5692        );
5693        assert_eq!(*follower_edit_event_count.read(), 3);
5694
5695        // Removing an empty set of excerpts is a noop.
5696        leader_multibuffer.update(cx, |leader, cx| {
5697            leader.remove_excerpts([], cx);
5698        });
5699        assert_eq!(
5700            leader_multibuffer.read(cx).snapshot(cx).text(),
5701            follower_multibuffer.read(cx).snapshot(cx).text(),
5702        );
5703        assert_eq!(*follower_edit_event_count.read(), 3);
5704
5705        // Adding an empty set of excerpts is a noop.
5706        leader_multibuffer.update(cx, |leader, cx| {
5707            leader.push_excerpts::<usize>(buffer_2.clone(), [], cx);
5708        });
5709        assert_eq!(
5710            leader_multibuffer.read(cx).snapshot(cx).text(),
5711            follower_multibuffer.read(cx).snapshot(cx).text(),
5712        );
5713        assert_eq!(*follower_edit_event_count.read(), 3);
5714
5715        leader_multibuffer.update(cx, |leader, cx| {
5716            leader.clear(cx);
5717        });
5718        assert_eq!(
5719            leader_multibuffer.read(cx).snapshot(cx).text(),
5720            follower_multibuffer.read(cx).snapshot(cx).text(),
5721        );
5722        assert_eq!(*follower_edit_event_count.read(), 4);
5723    }
5724
5725    #[gpui::test]
5726    fn test_expand_excerpts(cx: &mut AppContext) {
5727        let buffer = cx.new_model(|cx| Buffer::local(sample_text(20, 3, 'a'), cx));
5728        let multibuffer = cx.new_model(|_| MultiBuffer::new(Capability::ReadWrite));
5729
5730        multibuffer.update(cx, |multibuffer, cx| {
5731            multibuffer.push_excerpts_with_context_lines(
5732                buffer.clone(),
5733                vec![
5734                    // Note that in this test, this first excerpt
5735                    // does not contain a new line
5736                    Point::new(3, 2)..Point::new(3, 3),
5737                    Point::new(7, 1)..Point::new(7, 3),
5738                    Point::new(15, 0)..Point::new(15, 0),
5739                ],
5740                1,
5741                cx,
5742            )
5743        });
5744
5745        let snapshot = multibuffer.read(cx).snapshot(cx);
5746
5747        assert_eq!(
5748            snapshot.text(),
5749            concat!(
5750                "ccc\n", //
5751                "ddd\n", //
5752                "eee",   //
5753                "\n",    // End of excerpt
5754                "ggg\n", //
5755                "hhh\n", //
5756                "iii",   //
5757                "\n",    // End of excerpt
5758                "ooo\n", //
5759                "ppp\n", //
5760                "qqq",   // End of excerpt
5761            )
5762        );
5763        drop(snapshot);
5764
5765        multibuffer.update(cx, |multibuffer, cx| {
5766            multibuffer.expand_excerpts(
5767                multibuffer.excerpt_ids(),
5768                1,
5769                ExpandExcerptDirection::UpAndDown,
5770                cx,
5771            )
5772        });
5773
5774        let snapshot = multibuffer.read(cx).snapshot(cx);
5775
5776        // Expanding context lines causes the line containing 'fff' to appear in two different excerpts.
5777        // We don't attempt to merge them, because removing the excerpt could create inconsistency with other layers
5778        // that are tracking excerpt ids.
5779        assert_eq!(
5780            snapshot.text(),
5781            concat!(
5782                "bbb\n", //
5783                "ccc\n", //
5784                "ddd\n", //
5785                "eee\n", //
5786                "fff\n", // End of excerpt
5787                "fff\n", //
5788                "ggg\n", //
5789                "hhh\n", //
5790                "iii\n", //
5791                "jjj\n", // End of excerpt
5792                "nnn\n", //
5793                "ooo\n", //
5794                "ppp\n", //
5795                "qqq\n", //
5796                "rrr",   // End of excerpt
5797            )
5798        );
5799    }
5800
5801    #[gpui::test]
5802    fn test_push_excerpts_with_context_lines(cx: &mut AppContext) {
5803        let buffer = cx.new_model(|cx| Buffer::local(sample_text(20, 3, 'a'), cx));
5804        let multibuffer = cx.new_model(|_| MultiBuffer::new(Capability::ReadWrite));
5805        let anchor_ranges = multibuffer.update(cx, |multibuffer, cx| {
5806            multibuffer.push_excerpts_with_context_lines(
5807                buffer.clone(),
5808                vec![
5809                    // Note that in this test, this first excerpt
5810                    // does contain a new line
5811                    Point::new(3, 2)..Point::new(4, 2),
5812                    Point::new(7, 1)..Point::new(7, 3),
5813                    Point::new(15, 0)..Point::new(15, 0),
5814                ],
5815                2,
5816                cx,
5817            )
5818        });
5819
5820        let snapshot = multibuffer.read(cx).snapshot(cx);
5821        assert_eq!(
5822            snapshot.text(),
5823            concat!(
5824                "bbb\n", // Preserve newlines
5825                "ccc\n", //
5826                "ddd\n", //
5827                "eee\n", //
5828                "fff\n", //
5829                "ggg\n", //
5830                "hhh\n", //
5831                "iii\n", //
5832                "jjj\n", //
5833                "nnn\n", //
5834                "ooo\n", //
5835                "ppp\n", //
5836                "qqq\n", //
5837                "rrr",   //
5838            )
5839        );
5840
5841        assert_eq!(
5842            anchor_ranges
5843                .iter()
5844                .map(|range| range.to_point(&snapshot))
5845                .collect::<Vec<_>>(),
5846            vec![
5847                Point::new(2, 2)..Point::new(3, 2),
5848                Point::new(6, 1)..Point::new(6, 3),
5849                Point::new(11, 0)..Point::new(11, 0)
5850            ]
5851        );
5852    }
5853
5854    #[gpui::test(iterations = 100)]
5855    async fn test_push_multiple_excerpts_with_context_lines(cx: &mut TestAppContext) {
5856        let buffer_1 = cx.new_model(|cx| Buffer::local(sample_text(20, 3, 'a'), cx));
5857        let buffer_2 = cx.new_model(|cx| Buffer::local(sample_text(15, 4, 'a'), cx));
5858        let snapshot_1 = buffer_1.update(cx, |buffer, _| buffer.snapshot());
5859        let snapshot_2 = buffer_2.update(cx, |buffer, _| buffer.snapshot());
5860        let ranges_1 = vec![
5861            snapshot_1.anchor_before(Point::new(3, 2))..snapshot_1.anchor_before(Point::new(4, 2)),
5862            snapshot_1.anchor_before(Point::new(7, 1))..snapshot_1.anchor_before(Point::new(7, 3)),
5863            snapshot_1.anchor_before(Point::new(15, 0))
5864                ..snapshot_1.anchor_before(Point::new(15, 0)),
5865        ];
5866        let ranges_2 = vec![
5867            snapshot_2.anchor_before(Point::new(2, 1))..snapshot_2.anchor_before(Point::new(3, 1)),
5868            snapshot_2.anchor_before(Point::new(10, 0))
5869                ..snapshot_2.anchor_before(Point::new(10, 2)),
5870        ];
5871
5872        let multibuffer = cx.new_model(|_| MultiBuffer::new(Capability::ReadWrite));
5873        let anchor_ranges = multibuffer
5874            .update(cx, |multibuffer, cx| {
5875                multibuffer.push_multiple_excerpts_with_context_lines(
5876                    vec![(buffer_1.clone(), ranges_1), (buffer_2.clone(), ranges_2)],
5877                    2,
5878                    cx,
5879                )
5880            })
5881            .await;
5882
5883        let snapshot = multibuffer.update(cx, |multibuffer, cx| multibuffer.snapshot(cx));
5884        assert_eq!(
5885            snapshot.text(),
5886            concat!(
5887                "bbb\n", // buffer_1
5888                "ccc\n", //
5889                "ddd\n", // <-- excerpt 1
5890                "eee\n", // <-- excerpt 1
5891                "fff\n", //
5892                "ggg\n", //
5893                "hhh\n", // <-- excerpt 2
5894                "iii\n", //
5895                "jjj\n", //
5896                //
5897                "nnn\n", //
5898                "ooo\n", //
5899                "ppp\n", // <-- excerpt 3
5900                "qqq\n", //
5901                "rrr\n", //
5902                //
5903                "aaaa\n", // buffer 2
5904                "bbbb\n", //
5905                "cccc\n", // <-- excerpt 4
5906                "dddd\n", // <-- excerpt 4
5907                "eeee\n", //
5908                "ffff\n", //
5909                //
5910                "iiii\n", //
5911                "jjjj\n", //
5912                "kkkk\n", // <-- excerpt 5
5913                "llll\n", //
5914                "mmmm",   //
5915            )
5916        );
5917
5918        assert_eq!(
5919            anchor_ranges
5920                .iter()
5921                .map(|range| range.to_point(&snapshot))
5922                .collect::<Vec<_>>(),
5923            vec![
5924                Point::new(2, 2)..Point::new(3, 2),
5925                Point::new(6, 1)..Point::new(6, 3),
5926                Point::new(11, 0)..Point::new(11, 0),
5927                Point::new(16, 1)..Point::new(17, 1),
5928                Point::new(22, 0)..Point::new(22, 2)
5929            ]
5930        );
5931    }
5932
5933    #[gpui::test]
5934    fn test_empty_multibuffer(cx: &mut AppContext) {
5935        let multibuffer = cx.new_model(|_| MultiBuffer::new(Capability::ReadWrite));
5936
5937        let snapshot = multibuffer.read(cx).snapshot(cx);
5938        assert_eq!(snapshot.text(), "");
5939        assert_eq!(
5940            snapshot.buffer_rows(MultiBufferRow(0)).collect::<Vec<_>>(),
5941            &[Some(0)]
5942        );
5943        assert_eq!(
5944            snapshot.buffer_rows(MultiBufferRow(1)).collect::<Vec<_>>(),
5945            &[]
5946        );
5947    }
5948
5949    #[gpui::test]
5950    fn test_singleton_multibuffer_anchors(cx: &mut AppContext) {
5951        let buffer = cx.new_model(|cx| Buffer::local("abcd", cx));
5952        let multibuffer = cx.new_model(|cx| MultiBuffer::singleton(buffer.clone(), cx));
5953        let old_snapshot = multibuffer.read(cx).snapshot(cx);
5954        buffer.update(cx, |buffer, cx| {
5955            buffer.edit([(0..0, "X")], None, cx);
5956            buffer.edit([(5..5, "Y")], None, cx);
5957        });
5958        let new_snapshot = multibuffer.read(cx).snapshot(cx);
5959
5960        assert_eq!(old_snapshot.text(), "abcd");
5961        assert_eq!(new_snapshot.text(), "XabcdY");
5962
5963        assert_eq!(old_snapshot.anchor_before(0).to_offset(&new_snapshot), 0);
5964        assert_eq!(old_snapshot.anchor_after(0).to_offset(&new_snapshot), 1);
5965        assert_eq!(old_snapshot.anchor_before(4).to_offset(&new_snapshot), 5);
5966        assert_eq!(old_snapshot.anchor_after(4).to_offset(&new_snapshot), 6);
5967    }
5968
5969    #[gpui::test]
5970    fn test_multibuffer_anchors(cx: &mut AppContext) {
5971        let buffer_1 = cx.new_model(|cx| Buffer::local("abcd", cx));
5972        let buffer_2 = cx.new_model(|cx| Buffer::local("efghi", cx));
5973        let multibuffer = cx.new_model(|cx| {
5974            let mut multibuffer = MultiBuffer::new(Capability::ReadWrite);
5975            multibuffer.push_excerpts(
5976                buffer_1.clone(),
5977                [ExcerptRange {
5978                    context: 0..4,
5979                    primary: None,
5980                }],
5981                cx,
5982            );
5983            multibuffer.push_excerpts(
5984                buffer_2.clone(),
5985                [ExcerptRange {
5986                    context: 0..5,
5987                    primary: None,
5988                }],
5989                cx,
5990            );
5991            multibuffer
5992        });
5993        let old_snapshot = multibuffer.read(cx).snapshot(cx);
5994
5995        assert_eq!(old_snapshot.anchor_before(0).to_offset(&old_snapshot), 0);
5996        assert_eq!(old_snapshot.anchor_after(0).to_offset(&old_snapshot), 0);
5997        assert_eq!(Anchor::min().to_offset(&old_snapshot), 0);
5998        assert_eq!(Anchor::min().to_offset(&old_snapshot), 0);
5999        assert_eq!(Anchor::max().to_offset(&old_snapshot), 10);
6000        assert_eq!(Anchor::max().to_offset(&old_snapshot), 10);
6001
6002        buffer_1.update(cx, |buffer, cx| {
6003            buffer.edit([(0..0, "W")], None, cx);
6004            buffer.edit([(5..5, "X")], None, cx);
6005        });
6006        buffer_2.update(cx, |buffer, cx| {
6007            buffer.edit([(0..0, "Y")], None, cx);
6008            buffer.edit([(6..6, "Z")], None, cx);
6009        });
6010        let new_snapshot = multibuffer.read(cx).snapshot(cx);
6011
6012        assert_eq!(old_snapshot.text(), "abcd\nefghi");
6013        assert_eq!(new_snapshot.text(), "WabcdX\nYefghiZ");
6014
6015        assert_eq!(old_snapshot.anchor_before(0).to_offset(&new_snapshot), 0);
6016        assert_eq!(old_snapshot.anchor_after(0).to_offset(&new_snapshot), 1);
6017        assert_eq!(old_snapshot.anchor_before(1).to_offset(&new_snapshot), 2);
6018        assert_eq!(old_snapshot.anchor_after(1).to_offset(&new_snapshot), 2);
6019        assert_eq!(old_snapshot.anchor_before(2).to_offset(&new_snapshot), 3);
6020        assert_eq!(old_snapshot.anchor_after(2).to_offset(&new_snapshot), 3);
6021        assert_eq!(old_snapshot.anchor_before(5).to_offset(&new_snapshot), 7);
6022        assert_eq!(old_snapshot.anchor_after(5).to_offset(&new_snapshot), 8);
6023        assert_eq!(old_snapshot.anchor_before(10).to_offset(&new_snapshot), 13);
6024        assert_eq!(old_snapshot.anchor_after(10).to_offset(&new_snapshot), 14);
6025    }
6026
6027    #[gpui::test]
6028    fn test_resolving_anchors_after_replacing_their_excerpts(cx: &mut AppContext) {
6029        let buffer_1 = cx.new_model(|cx| Buffer::local("abcd", cx));
6030        let buffer_2 = cx.new_model(|cx| Buffer::local("ABCDEFGHIJKLMNOP", cx));
6031        let multibuffer = cx.new_model(|_| MultiBuffer::new(Capability::ReadWrite));
6032
6033        // Create an insertion id in buffer 1 that doesn't exist in buffer 2.
6034        // Add an excerpt from buffer 1 that spans this new insertion.
6035        buffer_1.update(cx, |buffer, cx| buffer.edit([(4..4, "123")], None, cx));
6036        let excerpt_id_1 = multibuffer.update(cx, |multibuffer, cx| {
6037            multibuffer
6038                .push_excerpts(
6039                    buffer_1.clone(),
6040                    [ExcerptRange {
6041                        context: 0..7,
6042                        primary: None,
6043                    }],
6044                    cx,
6045                )
6046                .pop()
6047                .unwrap()
6048        });
6049
6050        let snapshot_1 = multibuffer.read(cx).snapshot(cx);
6051        assert_eq!(snapshot_1.text(), "abcd123");
6052
6053        // Replace the buffer 1 excerpt with new excerpts from buffer 2.
6054        let (excerpt_id_2, excerpt_id_3) = multibuffer.update(cx, |multibuffer, cx| {
6055            multibuffer.remove_excerpts([excerpt_id_1], cx);
6056            let mut ids = multibuffer
6057                .push_excerpts(
6058                    buffer_2.clone(),
6059                    [
6060                        ExcerptRange {
6061                            context: 0..4,
6062                            primary: None,
6063                        },
6064                        ExcerptRange {
6065                            context: 6..10,
6066                            primary: None,
6067                        },
6068                        ExcerptRange {
6069                            context: 12..16,
6070                            primary: None,
6071                        },
6072                    ],
6073                    cx,
6074                )
6075                .into_iter();
6076            (ids.next().unwrap(), ids.next().unwrap())
6077        });
6078        let snapshot_2 = multibuffer.read(cx).snapshot(cx);
6079        assert_eq!(snapshot_2.text(), "ABCD\nGHIJ\nMNOP");
6080
6081        // The old excerpt id doesn't get reused.
6082        assert_ne!(excerpt_id_2, excerpt_id_1);
6083
6084        // Resolve some anchors from the previous snapshot in the new snapshot.
6085        // The current excerpts are from a different buffer, so we don't attempt to
6086        // resolve the old text anchor in the new buffer.
6087        assert_eq!(
6088            snapshot_2.summary_for_anchor::<usize>(&snapshot_1.anchor_before(2)),
6089            0
6090        );
6091        assert_eq!(
6092            snapshot_2.summaries_for_anchors::<usize, _>(&[
6093                snapshot_1.anchor_before(2),
6094                snapshot_1.anchor_after(3)
6095            ]),
6096            vec![0, 0]
6097        );
6098
6099        // Refresh anchors from the old snapshot. The return value indicates that both
6100        // anchors lost their original excerpt.
6101        let refresh =
6102            snapshot_2.refresh_anchors(&[snapshot_1.anchor_before(2), snapshot_1.anchor_after(3)]);
6103        assert_eq!(
6104            refresh,
6105            &[
6106                (0, snapshot_2.anchor_before(0), false),
6107                (1, snapshot_2.anchor_after(0), false),
6108            ]
6109        );
6110
6111        // Replace the middle excerpt with a smaller excerpt in buffer 2,
6112        // that intersects the old excerpt.
6113        let excerpt_id_5 = multibuffer.update(cx, |multibuffer, cx| {
6114            multibuffer.remove_excerpts([excerpt_id_3], cx);
6115            multibuffer
6116                .insert_excerpts_after(
6117                    excerpt_id_2,
6118                    buffer_2.clone(),
6119                    [ExcerptRange {
6120                        context: 5..8,
6121                        primary: None,
6122                    }],
6123                    cx,
6124                )
6125                .pop()
6126                .unwrap()
6127        });
6128
6129        let snapshot_3 = multibuffer.read(cx).snapshot(cx);
6130        assert_eq!(snapshot_3.text(), "ABCD\nFGH\nMNOP");
6131        assert_ne!(excerpt_id_5, excerpt_id_3);
6132
6133        // Resolve some anchors from the previous snapshot in the new snapshot.
6134        // The third anchor can't be resolved, since its excerpt has been removed,
6135        // so it resolves to the same position as its predecessor.
6136        let anchors = [
6137            snapshot_2.anchor_before(0),
6138            snapshot_2.anchor_after(2),
6139            snapshot_2.anchor_after(6),
6140            snapshot_2.anchor_after(14),
6141        ];
6142        assert_eq!(
6143            snapshot_3.summaries_for_anchors::<usize, _>(&anchors),
6144            &[0, 2, 9, 13]
6145        );
6146
6147        let new_anchors = snapshot_3.refresh_anchors(&anchors);
6148        assert_eq!(
6149            new_anchors.iter().map(|a| (a.0, a.2)).collect::<Vec<_>>(),
6150            &[(0, true), (1, true), (2, true), (3, true)]
6151        );
6152        assert_eq!(
6153            snapshot_3.summaries_for_anchors::<usize, _>(new_anchors.iter().map(|a| &a.1)),
6154            &[0, 2, 7, 13]
6155        );
6156    }
6157
6158    #[gpui::test(iterations = 100)]
6159    fn test_random_multibuffer(cx: &mut AppContext, mut rng: StdRng) {
6160        let operations = env::var("OPERATIONS")
6161            .map(|i| i.parse().expect("invalid `OPERATIONS` variable"))
6162            .unwrap_or(10);
6163
6164        let mut buffers: Vec<Model<Buffer>> = Vec::new();
6165        let multibuffer = cx.new_model(|_| MultiBuffer::new(Capability::ReadWrite));
6166        let mut excerpt_ids = Vec::<ExcerptId>::new();
6167        let mut expected_excerpts = Vec::<(Model<Buffer>, Range<text::Anchor>)>::new();
6168        let mut anchors = Vec::new();
6169        let mut old_versions = Vec::new();
6170
6171        for _ in 0..operations {
6172            match rng.gen_range(0..100) {
6173                0..=14 if !buffers.is_empty() => {
6174                    let buffer = buffers.choose(&mut rng).unwrap();
6175                    buffer.update(cx, |buf, cx| buf.randomly_edit(&mut rng, 5, cx));
6176                }
6177                15..=19 if !expected_excerpts.is_empty() => {
6178                    multibuffer.update(cx, |multibuffer, cx| {
6179                        let ids = multibuffer.excerpt_ids();
6180                        let mut excerpts = HashSet::default();
6181                        for _ in 0..rng.gen_range(0..ids.len()) {
6182                            excerpts.extend(ids.choose(&mut rng).copied());
6183                        }
6184
6185                        let line_count = rng.gen_range(0..5);
6186
6187                        let excerpt_ixs = excerpts
6188                            .iter()
6189                            .map(|id| excerpt_ids.iter().position(|i| i == id).unwrap())
6190                            .collect::<Vec<_>>();
6191                        log::info!("Expanding excerpts {excerpt_ixs:?} by {line_count} lines");
6192                        multibuffer.expand_excerpts(
6193                            excerpts.iter().cloned(),
6194                            line_count,
6195                            ExpandExcerptDirection::UpAndDown,
6196                            cx,
6197                        );
6198
6199                        if line_count > 0 {
6200                            for id in excerpts {
6201                                let excerpt_ix = excerpt_ids.iter().position(|&i| i == id).unwrap();
6202                                let (buffer, range) = &mut expected_excerpts[excerpt_ix];
6203                                let snapshot = buffer.read(cx).snapshot();
6204                                let mut point_range = range.to_point(&snapshot);
6205                                point_range.start =
6206                                    Point::new(point_range.start.row.saturating_sub(line_count), 0);
6207                                point_range.end = snapshot.clip_point(
6208                                    Point::new(point_range.end.row + line_count, 0),
6209                                    Bias::Left,
6210                                );
6211                                point_range.end.column = snapshot.line_len(point_range.end.row);
6212                                *range = snapshot.anchor_before(point_range.start)
6213                                    ..snapshot.anchor_after(point_range.end);
6214                            }
6215                        }
6216                    });
6217                }
6218                20..=29 if !expected_excerpts.is_empty() => {
6219                    let mut ids_to_remove = vec![];
6220                    for _ in 0..rng.gen_range(1..=3) {
6221                        if expected_excerpts.is_empty() {
6222                            break;
6223                        }
6224
6225                        let ix = rng.gen_range(0..expected_excerpts.len());
6226                        ids_to_remove.push(excerpt_ids.remove(ix));
6227                        let (buffer, range) = expected_excerpts.remove(ix);
6228                        let buffer = buffer.read(cx);
6229                        log::info!(
6230                            "Removing excerpt {}: {:?}",
6231                            ix,
6232                            buffer
6233                                .text_for_range(range.to_offset(buffer))
6234                                .collect::<String>(),
6235                        );
6236                    }
6237                    let snapshot = multibuffer.read(cx).read(cx);
6238                    ids_to_remove.sort_unstable_by(|a, b| a.cmp(b, &snapshot));
6239                    drop(snapshot);
6240                    multibuffer.update(cx, |multibuffer, cx| {
6241                        multibuffer.remove_excerpts(ids_to_remove, cx)
6242                    });
6243                }
6244                30..=39 if !expected_excerpts.is_empty() => {
6245                    let multibuffer = multibuffer.read(cx).read(cx);
6246                    let offset =
6247                        multibuffer.clip_offset(rng.gen_range(0..=multibuffer.len()), Bias::Left);
6248                    let bias = if rng.gen() { Bias::Left } else { Bias::Right };
6249                    log::info!("Creating anchor at {} with bias {:?}", offset, bias);
6250                    anchors.push(multibuffer.anchor_at(offset, bias));
6251                    anchors.sort_by(|a, b| a.cmp(b, &multibuffer));
6252                }
6253                40..=44 if !anchors.is_empty() => {
6254                    let multibuffer = multibuffer.read(cx).read(cx);
6255                    let prev_len = anchors.len();
6256                    anchors = multibuffer
6257                        .refresh_anchors(&anchors)
6258                        .into_iter()
6259                        .map(|a| a.1)
6260                        .collect();
6261
6262                    // Ensure the newly-refreshed anchors point to a valid excerpt and don't
6263                    // overshoot its boundaries.
6264                    assert_eq!(anchors.len(), prev_len);
6265                    for anchor in &anchors {
6266                        if anchor.excerpt_id == ExcerptId::min()
6267                            || anchor.excerpt_id == ExcerptId::max()
6268                        {
6269                            continue;
6270                        }
6271
6272                        let excerpt = multibuffer.excerpt(anchor.excerpt_id).unwrap();
6273                        assert_eq!(excerpt.id, anchor.excerpt_id);
6274                        assert!(excerpt.contains(anchor));
6275                    }
6276                }
6277                _ => {
6278                    let buffer_handle = if buffers.is_empty() || rng.gen_bool(0.4) {
6279                        let base_text = util::RandomCharIter::new(&mut rng)
6280                            .take(25)
6281                            .collect::<String>();
6282
6283                        buffers.push(cx.new_model(|cx| Buffer::local(base_text, cx)));
6284                        buffers.last().unwrap()
6285                    } else {
6286                        buffers.choose(&mut rng).unwrap()
6287                    };
6288
6289                    let buffer = buffer_handle.read(cx);
6290                    let end_ix = buffer.clip_offset(rng.gen_range(0..=buffer.len()), Bias::Right);
6291                    let start_ix = buffer.clip_offset(rng.gen_range(0..=end_ix), Bias::Left);
6292                    let anchor_range = buffer.anchor_before(start_ix)..buffer.anchor_after(end_ix);
6293                    let prev_excerpt_ix = rng.gen_range(0..=expected_excerpts.len());
6294                    let prev_excerpt_id = excerpt_ids
6295                        .get(prev_excerpt_ix)
6296                        .cloned()
6297                        .unwrap_or_else(ExcerptId::max);
6298                    let excerpt_ix = (prev_excerpt_ix + 1).min(expected_excerpts.len());
6299
6300                    log::info!(
6301                        "Inserting excerpt at {} of {} for buffer {}: {:?}[{:?}] = {:?}",
6302                        excerpt_ix,
6303                        expected_excerpts.len(),
6304                        buffer_handle.read(cx).remote_id(),
6305                        buffer.text(),
6306                        start_ix..end_ix,
6307                        &buffer.text()[start_ix..end_ix]
6308                    );
6309
6310                    let excerpt_id = multibuffer.update(cx, |multibuffer, cx| {
6311                        multibuffer
6312                            .insert_excerpts_after(
6313                                prev_excerpt_id,
6314                                buffer_handle.clone(),
6315                                [ExcerptRange {
6316                                    context: start_ix..end_ix,
6317                                    primary: None,
6318                                }],
6319                                cx,
6320                            )
6321                            .pop()
6322                            .unwrap()
6323                    });
6324
6325                    excerpt_ids.insert(excerpt_ix, excerpt_id);
6326                    expected_excerpts.insert(excerpt_ix, (buffer_handle.clone(), anchor_range));
6327                }
6328            }
6329
6330            if rng.gen_bool(0.3) {
6331                multibuffer.update(cx, |multibuffer, cx| {
6332                    old_versions.push((multibuffer.snapshot(cx), multibuffer.subscribe()));
6333                })
6334            }
6335
6336            let snapshot = multibuffer.read(cx).snapshot(cx);
6337
6338            let mut excerpt_starts = Vec::new();
6339            let mut expected_text = String::new();
6340            let mut expected_buffer_rows = Vec::new();
6341            for (buffer, range) in &expected_excerpts {
6342                let buffer = buffer.read(cx);
6343                let buffer_range = range.to_offset(buffer);
6344
6345                excerpt_starts.push(TextSummary::from(expected_text.as_str()));
6346                expected_text.extend(buffer.text_for_range(buffer_range.clone()));
6347                expected_text.push('\n');
6348
6349                let buffer_row_range = buffer.offset_to_point(buffer_range.start).row
6350                    ..=buffer.offset_to_point(buffer_range.end).row;
6351                for row in buffer_row_range {
6352                    expected_buffer_rows.push(Some(row));
6353                }
6354            }
6355            // Remove final trailing newline.
6356            if !expected_excerpts.is_empty() {
6357                expected_text.pop();
6358            }
6359
6360            // Always report one buffer row
6361            if expected_buffer_rows.is_empty() {
6362                expected_buffer_rows.push(Some(0));
6363            }
6364
6365            assert_eq!(snapshot.text(), expected_text);
6366            log::info!("MultiBuffer text: {:?}", expected_text);
6367
6368            assert_eq!(
6369                snapshot.buffer_rows(MultiBufferRow(0)).collect::<Vec<_>>(),
6370                expected_buffer_rows,
6371            );
6372
6373            for _ in 0..5 {
6374                let start_row = rng.gen_range(0..=expected_buffer_rows.len());
6375                assert_eq!(
6376                    snapshot
6377                        .buffer_rows(MultiBufferRow(start_row as u32))
6378                        .collect::<Vec<_>>(),
6379                    &expected_buffer_rows[start_row..],
6380                    "buffer_rows({})",
6381                    start_row
6382                );
6383            }
6384
6385            assert_eq!(
6386                snapshot.max_buffer_row().0,
6387                expected_buffer_rows.into_iter().flatten().max().unwrap()
6388            );
6389
6390            let mut excerpt_starts = excerpt_starts.into_iter();
6391            for (buffer, range) in &expected_excerpts {
6392                let buffer = buffer.read(cx);
6393                let buffer_id = buffer.remote_id();
6394                let buffer_range = range.to_offset(buffer);
6395                let buffer_start_point = buffer.offset_to_point(buffer_range.start);
6396                let buffer_start_point_utf16 =
6397                    buffer.text_summary_for_range::<PointUtf16, _>(0..buffer_range.start);
6398
6399                let excerpt_start = excerpt_starts.next().unwrap();
6400                let mut offset = excerpt_start.len;
6401                let mut buffer_offset = buffer_range.start;
6402                let mut point = excerpt_start.lines;
6403                let mut buffer_point = buffer_start_point;
6404                let mut point_utf16 = excerpt_start.lines_utf16();
6405                let mut buffer_point_utf16 = buffer_start_point_utf16;
6406                for ch in buffer
6407                    .snapshot()
6408                    .chunks(buffer_range.clone(), false)
6409                    .flat_map(|c| c.text.chars())
6410                {
6411                    for _ in 0..ch.len_utf8() {
6412                        let left_offset = snapshot.clip_offset(offset, Bias::Left);
6413                        let right_offset = snapshot.clip_offset(offset, Bias::Right);
6414                        let buffer_left_offset = buffer.clip_offset(buffer_offset, Bias::Left);
6415                        let buffer_right_offset = buffer.clip_offset(buffer_offset, Bias::Right);
6416                        assert_eq!(
6417                            left_offset,
6418                            excerpt_start.len + (buffer_left_offset - buffer_range.start),
6419                            "clip_offset({:?}, Left). buffer: {:?}, buffer offset: {:?}",
6420                            offset,
6421                            buffer_id,
6422                            buffer_offset,
6423                        );
6424                        assert_eq!(
6425                            right_offset,
6426                            excerpt_start.len + (buffer_right_offset - buffer_range.start),
6427                            "clip_offset({:?}, Right). buffer: {:?}, buffer offset: {:?}",
6428                            offset,
6429                            buffer_id,
6430                            buffer_offset,
6431                        );
6432
6433                        let left_point = snapshot.clip_point(point, Bias::Left);
6434                        let right_point = snapshot.clip_point(point, Bias::Right);
6435                        let buffer_left_point = buffer.clip_point(buffer_point, Bias::Left);
6436                        let buffer_right_point = buffer.clip_point(buffer_point, Bias::Right);
6437                        assert_eq!(
6438                            left_point,
6439                            excerpt_start.lines + (buffer_left_point - buffer_start_point),
6440                            "clip_point({:?}, Left). buffer: {:?}, buffer point: {:?}",
6441                            point,
6442                            buffer_id,
6443                            buffer_point,
6444                        );
6445                        assert_eq!(
6446                            right_point,
6447                            excerpt_start.lines + (buffer_right_point - buffer_start_point),
6448                            "clip_point({:?}, Right). buffer: {:?}, buffer point: {:?}",
6449                            point,
6450                            buffer_id,
6451                            buffer_point,
6452                        );
6453
6454                        assert_eq!(
6455                            snapshot.point_to_offset(left_point),
6456                            left_offset,
6457                            "point_to_offset({:?})",
6458                            left_point,
6459                        );
6460                        assert_eq!(
6461                            snapshot.offset_to_point(left_offset),
6462                            left_point,
6463                            "offset_to_point({:?})",
6464                            left_offset,
6465                        );
6466
6467                        offset += 1;
6468                        buffer_offset += 1;
6469                        if ch == '\n' {
6470                            point += Point::new(1, 0);
6471                            buffer_point += Point::new(1, 0);
6472                        } else {
6473                            point += Point::new(0, 1);
6474                            buffer_point += Point::new(0, 1);
6475                        }
6476                    }
6477
6478                    for _ in 0..ch.len_utf16() {
6479                        let left_point_utf16 =
6480                            snapshot.clip_point_utf16(Unclipped(point_utf16), Bias::Left);
6481                        let right_point_utf16 =
6482                            snapshot.clip_point_utf16(Unclipped(point_utf16), Bias::Right);
6483                        let buffer_left_point_utf16 =
6484                            buffer.clip_point_utf16(Unclipped(buffer_point_utf16), Bias::Left);
6485                        let buffer_right_point_utf16 =
6486                            buffer.clip_point_utf16(Unclipped(buffer_point_utf16), Bias::Right);
6487                        assert_eq!(
6488                            left_point_utf16,
6489                            excerpt_start.lines_utf16()
6490                                + (buffer_left_point_utf16 - buffer_start_point_utf16),
6491                            "clip_point_utf16({:?}, Left). buffer: {:?}, buffer point_utf16: {:?}",
6492                            point_utf16,
6493                            buffer_id,
6494                            buffer_point_utf16,
6495                        );
6496                        assert_eq!(
6497                            right_point_utf16,
6498                            excerpt_start.lines_utf16()
6499                                + (buffer_right_point_utf16 - buffer_start_point_utf16),
6500                            "clip_point_utf16({:?}, Right). buffer: {:?}, buffer point_utf16: {:?}",
6501                            point_utf16,
6502                            buffer_id,
6503                            buffer_point_utf16,
6504                        );
6505
6506                        if ch == '\n' {
6507                            point_utf16 += PointUtf16::new(1, 0);
6508                            buffer_point_utf16 += PointUtf16::new(1, 0);
6509                        } else {
6510                            point_utf16 += PointUtf16::new(0, 1);
6511                            buffer_point_utf16 += PointUtf16::new(0, 1);
6512                        }
6513                    }
6514                }
6515            }
6516
6517            for (row, line) in expected_text.split('\n').enumerate() {
6518                assert_eq!(
6519                    snapshot.line_len(MultiBufferRow(row as u32)),
6520                    line.len() as u32,
6521                    "line_len({}).",
6522                    row
6523                );
6524            }
6525
6526            let text_rope = Rope::from(expected_text.as_str());
6527            for _ in 0..10 {
6528                let end_ix = text_rope.clip_offset(rng.gen_range(0..=text_rope.len()), Bias::Right);
6529                let start_ix = text_rope.clip_offset(rng.gen_range(0..=end_ix), Bias::Left);
6530
6531                let text_for_range = snapshot
6532                    .text_for_range(start_ix..end_ix)
6533                    .collect::<String>();
6534                assert_eq!(
6535                    text_for_range,
6536                    &expected_text[start_ix..end_ix],
6537                    "incorrect text for range {:?}",
6538                    start_ix..end_ix
6539                );
6540
6541                let excerpted_buffer_ranges = multibuffer
6542                    .read(cx)
6543                    .range_to_buffer_ranges(start_ix..end_ix, cx);
6544                let excerpted_buffers_text = excerpted_buffer_ranges
6545                    .iter()
6546                    .map(|(buffer, buffer_range, _)| {
6547                        buffer
6548                            .read(cx)
6549                            .text_for_range(buffer_range.clone())
6550                            .collect::<String>()
6551                    })
6552                    .collect::<Vec<_>>()
6553                    .join("\n");
6554                assert_eq!(excerpted_buffers_text, text_for_range);
6555                if !expected_excerpts.is_empty() {
6556                    assert!(!excerpted_buffer_ranges.is_empty());
6557                }
6558
6559                let expected_summary = TextSummary::from(&expected_text[start_ix..end_ix]);
6560                assert_eq!(
6561                    snapshot.text_summary_for_range::<TextSummary, _>(start_ix..end_ix),
6562                    expected_summary,
6563                    "incorrect summary for range {:?}",
6564                    start_ix..end_ix
6565                );
6566            }
6567
6568            // Anchor resolution
6569            let summaries = snapshot.summaries_for_anchors::<usize, _>(&anchors);
6570            assert_eq!(anchors.len(), summaries.len());
6571            for (anchor, resolved_offset) in anchors.iter().zip(summaries) {
6572                assert!(resolved_offset <= snapshot.len());
6573                assert_eq!(
6574                    snapshot.summary_for_anchor::<usize>(anchor),
6575                    resolved_offset
6576                );
6577            }
6578
6579            for _ in 0..10 {
6580                let end_ix = text_rope.clip_offset(rng.gen_range(0..=text_rope.len()), Bias::Right);
6581                assert_eq!(
6582                    snapshot.reversed_chars_at(end_ix).collect::<String>(),
6583                    expected_text[..end_ix].chars().rev().collect::<String>(),
6584                );
6585            }
6586
6587            for _ in 0..10 {
6588                let end_ix = rng.gen_range(0..=text_rope.len());
6589                let start_ix = rng.gen_range(0..=end_ix);
6590                assert_eq!(
6591                    snapshot
6592                        .bytes_in_range(start_ix..end_ix)
6593                        .flatten()
6594                        .copied()
6595                        .collect::<Vec<_>>(),
6596                    expected_text.as_bytes()[start_ix..end_ix].to_vec(),
6597                    "bytes_in_range({:?})",
6598                    start_ix..end_ix,
6599                );
6600            }
6601        }
6602
6603        let snapshot = multibuffer.read(cx).snapshot(cx);
6604        for (old_snapshot, subscription) in old_versions {
6605            let edits = subscription.consume().into_inner();
6606
6607            log::info!(
6608                "applying subscription edits to old text: {:?}: {:?}",
6609                old_snapshot.text(),
6610                edits,
6611            );
6612
6613            let mut text = old_snapshot.text();
6614            for edit in edits {
6615                let new_text: String = snapshot.text_for_range(edit.new.clone()).collect();
6616                text.replace_range(edit.new.start..edit.new.start + edit.old.len(), &new_text);
6617            }
6618            assert_eq!(text.to_string(), snapshot.text());
6619        }
6620    }
6621
6622    #[gpui::test]
6623    fn test_history(cx: &mut AppContext) {
6624        let test_settings = SettingsStore::test(cx);
6625        cx.set_global(test_settings);
6626        let group_interval: Duration = Duration::from_millis(1);
6627        let buffer_1 = cx.new_model(|cx| {
6628            let mut buf = Buffer::local("1234", cx);
6629            buf.set_group_interval(group_interval);
6630            buf
6631        });
6632        let buffer_2 = cx.new_model(|cx| {
6633            let mut buf = Buffer::local("5678", cx);
6634            buf.set_group_interval(group_interval);
6635            buf
6636        });
6637        let multibuffer = cx.new_model(|_| MultiBuffer::new(Capability::ReadWrite));
6638        multibuffer.update(cx, |this, _| {
6639            this.history.group_interval = group_interval;
6640        });
6641        multibuffer.update(cx, |multibuffer, cx| {
6642            multibuffer.push_excerpts(
6643                buffer_1.clone(),
6644                [ExcerptRange {
6645                    context: 0..buffer_1.read(cx).len(),
6646                    primary: None,
6647                }],
6648                cx,
6649            );
6650            multibuffer.push_excerpts(
6651                buffer_2.clone(),
6652                [ExcerptRange {
6653                    context: 0..buffer_2.read(cx).len(),
6654                    primary: None,
6655                }],
6656                cx,
6657            );
6658        });
6659
6660        let mut now = Instant::now();
6661
6662        multibuffer.update(cx, |multibuffer, cx| {
6663            let transaction_1 = multibuffer.start_transaction_at(now, cx).unwrap();
6664            multibuffer.edit(
6665                [
6666                    (Point::new(0, 0)..Point::new(0, 0), "A"),
6667                    (Point::new(1, 0)..Point::new(1, 0), "A"),
6668                ],
6669                None,
6670                cx,
6671            );
6672            multibuffer.edit(
6673                [
6674                    (Point::new(0, 1)..Point::new(0, 1), "B"),
6675                    (Point::new(1, 1)..Point::new(1, 1), "B"),
6676                ],
6677                None,
6678                cx,
6679            );
6680            multibuffer.end_transaction_at(now, cx);
6681            assert_eq!(multibuffer.read(cx).text(), "AB1234\nAB5678");
6682
6683            // Verify edited ranges for transaction 1
6684            assert_eq!(
6685                multibuffer.edited_ranges_for_transaction(transaction_1, cx),
6686                &[
6687                    Point::new(0, 0)..Point::new(0, 2),
6688                    Point::new(1, 0)..Point::new(1, 2)
6689                ]
6690            );
6691
6692            // Edit buffer 1 through the multibuffer
6693            now += 2 * group_interval;
6694            multibuffer.start_transaction_at(now, cx);
6695            multibuffer.edit([(2..2, "C")], None, cx);
6696            multibuffer.end_transaction_at(now, cx);
6697            assert_eq!(multibuffer.read(cx).text(), "ABC1234\nAB5678");
6698
6699            // Edit buffer 1 independently
6700            buffer_1.update(cx, |buffer_1, cx| {
6701                buffer_1.start_transaction_at(now);
6702                buffer_1.edit([(3..3, "D")], None, cx);
6703                buffer_1.end_transaction_at(now, cx);
6704
6705                now += 2 * group_interval;
6706                buffer_1.start_transaction_at(now);
6707                buffer_1.edit([(4..4, "E")], None, cx);
6708                buffer_1.end_transaction_at(now, cx);
6709            });
6710            assert_eq!(multibuffer.read(cx).text(), "ABCDE1234\nAB5678");
6711
6712            // An undo in the multibuffer undoes the multibuffer transaction
6713            // and also any individual buffer edits that have occurred since
6714            // that transaction.
6715            multibuffer.undo(cx);
6716            assert_eq!(multibuffer.read(cx).text(), "AB1234\nAB5678");
6717
6718            multibuffer.undo(cx);
6719            assert_eq!(multibuffer.read(cx).text(), "1234\n5678");
6720
6721            multibuffer.redo(cx);
6722            assert_eq!(multibuffer.read(cx).text(), "AB1234\nAB5678");
6723
6724            multibuffer.redo(cx);
6725            assert_eq!(multibuffer.read(cx).text(), "ABCDE1234\nAB5678");
6726
6727            // Undo buffer 2 independently.
6728            buffer_2.update(cx, |buffer_2, cx| buffer_2.undo(cx));
6729            assert_eq!(multibuffer.read(cx).text(), "ABCDE1234\n5678");
6730
6731            // An undo in the multibuffer undoes the components of the
6732            // the last multibuffer transaction that are not already undone.
6733            multibuffer.undo(cx);
6734            assert_eq!(multibuffer.read(cx).text(), "AB1234\n5678");
6735
6736            multibuffer.undo(cx);
6737            assert_eq!(multibuffer.read(cx).text(), "1234\n5678");
6738
6739            multibuffer.redo(cx);
6740            assert_eq!(multibuffer.read(cx).text(), "AB1234\nAB5678");
6741
6742            buffer_1.update(cx, |buffer_1, cx| buffer_1.redo(cx));
6743            assert_eq!(multibuffer.read(cx).text(), "ABCD1234\nAB5678");
6744
6745            // Redo stack gets cleared after an edit.
6746            now += 2 * group_interval;
6747            multibuffer.start_transaction_at(now, cx);
6748            multibuffer.edit([(0..0, "X")], None, cx);
6749            multibuffer.end_transaction_at(now, cx);
6750            assert_eq!(multibuffer.read(cx).text(), "XABCD1234\nAB5678");
6751            multibuffer.redo(cx);
6752            assert_eq!(multibuffer.read(cx).text(), "XABCD1234\nAB5678");
6753            multibuffer.undo(cx);
6754            assert_eq!(multibuffer.read(cx).text(), "ABCD1234\nAB5678");
6755            multibuffer.undo(cx);
6756            assert_eq!(multibuffer.read(cx).text(), "1234\n5678");
6757
6758            // Transactions can be grouped manually.
6759            multibuffer.redo(cx);
6760            multibuffer.redo(cx);
6761            assert_eq!(multibuffer.read(cx).text(), "XABCD1234\nAB5678");
6762            multibuffer.group_until_transaction(transaction_1, cx);
6763            multibuffer.undo(cx);
6764            assert_eq!(multibuffer.read(cx).text(), "1234\n5678");
6765            multibuffer.redo(cx);
6766            assert_eq!(multibuffer.read(cx).text(), "XABCD1234\nAB5678");
6767        });
6768    }
6769
6770    #[gpui::test]
6771    fn test_excerpts_in_ranges_no_ranges(cx: &mut AppContext) {
6772        let buffer_1 = cx.new_model(|cx| Buffer::local(sample_text(6, 6, 'a'), cx));
6773        let buffer_2 = cx.new_model(|cx| Buffer::local(sample_text(6, 6, 'g'), cx));
6774        let multibuffer = cx.new_model(|_| MultiBuffer::new(Capability::ReadWrite));
6775        multibuffer.update(cx, |multibuffer, cx| {
6776            multibuffer.push_excerpts(
6777                buffer_1.clone(),
6778                [ExcerptRange {
6779                    context: 0..buffer_1.read(cx).len(),
6780                    primary: None,
6781                }],
6782                cx,
6783            );
6784            multibuffer.push_excerpts(
6785                buffer_2.clone(),
6786                [ExcerptRange {
6787                    context: 0..buffer_2.read(cx).len(),
6788                    primary: None,
6789                }],
6790                cx,
6791            );
6792        });
6793
6794        let snapshot = multibuffer.update(cx, |multibuffer, cx| multibuffer.snapshot(cx));
6795
6796        let mut excerpts = snapshot.excerpts_in_ranges(iter::from_fn(|| None));
6797
6798        assert!(excerpts.next().is_none());
6799    }
6800
6801    fn validate_excerpts(
6802        actual: &[(ExcerptId, BufferId, Range<Anchor>)],
6803        expected: &Vec<(ExcerptId, BufferId, Range<Anchor>)>,
6804    ) {
6805        assert_eq!(actual.len(), expected.len());
6806
6807        actual
6808            .iter()
6809            .zip(expected)
6810            .map(|(actual, expected)| {
6811                assert_eq!(actual.0, expected.0);
6812                assert_eq!(actual.1, expected.1);
6813                assert_eq!(actual.2.start, expected.2.start);
6814                assert_eq!(actual.2.end, expected.2.end);
6815            })
6816            .collect_vec();
6817    }
6818
6819    fn map_range_from_excerpt(
6820        snapshot: &MultiBufferSnapshot,
6821        excerpt_id: ExcerptId,
6822        excerpt_buffer: &BufferSnapshot,
6823        range: Range<usize>,
6824    ) -> Range<Anchor> {
6825        snapshot
6826            .anchor_in_excerpt(excerpt_id, excerpt_buffer.anchor_before(range.start))
6827            .unwrap()
6828            ..snapshot
6829                .anchor_in_excerpt(excerpt_id, excerpt_buffer.anchor_after(range.end))
6830                .unwrap()
6831    }
6832
6833    fn make_expected_excerpt_info(
6834        snapshot: &MultiBufferSnapshot,
6835        cx: &mut AppContext,
6836        excerpt_id: ExcerptId,
6837        buffer: &Model<Buffer>,
6838        range: Range<usize>,
6839    ) -> (ExcerptId, BufferId, Range<Anchor>) {
6840        (
6841            excerpt_id,
6842            buffer.read(cx).remote_id(),
6843            map_range_from_excerpt(snapshot, excerpt_id, &buffer.read(cx).snapshot(), range),
6844        )
6845    }
6846
6847    #[gpui::test]
6848    fn test_excerpts_in_ranges_range_inside_the_excerpt(cx: &mut AppContext) {
6849        let buffer_1 = cx.new_model(|cx| Buffer::local(sample_text(6, 6, 'a'), cx));
6850        let buffer_2 = cx.new_model(|cx| Buffer::local(sample_text(6, 6, 'g'), cx));
6851        let buffer_len = buffer_1.read(cx).len();
6852        let multibuffer = cx.new_model(|_| MultiBuffer::new(Capability::ReadWrite));
6853        let mut expected_excerpt_id = ExcerptId(0);
6854
6855        multibuffer.update(cx, |multibuffer, cx| {
6856            expected_excerpt_id = multibuffer.push_excerpts(
6857                buffer_1.clone(),
6858                [ExcerptRange {
6859                    context: 0..buffer_1.read(cx).len(),
6860                    primary: None,
6861                }],
6862                cx,
6863            )[0];
6864            multibuffer.push_excerpts(
6865                buffer_2.clone(),
6866                [ExcerptRange {
6867                    context: 0..buffer_2.read(cx).len(),
6868                    primary: None,
6869                }],
6870                cx,
6871            );
6872        });
6873
6874        let snapshot = multibuffer.update(cx, |multibuffer, cx| multibuffer.snapshot(cx));
6875
6876        let range = snapshot
6877            .anchor_in_excerpt(expected_excerpt_id, buffer_1.read(cx).anchor_before(1))
6878            .unwrap()
6879            ..snapshot
6880                .anchor_in_excerpt(
6881                    expected_excerpt_id,
6882                    buffer_1.read(cx).anchor_after(buffer_len / 2),
6883                )
6884                .unwrap();
6885
6886        let expected_excerpts = vec![make_expected_excerpt_info(
6887            &snapshot,
6888            cx,
6889            expected_excerpt_id,
6890            &buffer_1,
6891            1..(buffer_len / 2),
6892        )];
6893
6894        let excerpts = snapshot
6895            .excerpts_in_ranges(vec![range.clone()].into_iter())
6896            .map(|(excerpt_id, buffer, actual_range)| {
6897                (
6898                    excerpt_id,
6899                    buffer.remote_id(),
6900                    map_range_from_excerpt(&snapshot, excerpt_id, buffer, actual_range),
6901                )
6902            })
6903            .collect_vec();
6904
6905        validate_excerpts(&excerpts, &expected_excerpts);
6906    }
6907
6908    #[gpui::test]
6909    fn test_excerpts_in_ranges_range_crosses_excerpts_boundary(cx: &mut AppContext) {
6910        let buffer_1 = cx.new_model(|cx| Buffer::local(sample_text(6, 6, 'a'), cx));
6911        let buffer_2 = cx.new_model(|cx| Buffer::local(sample_text(6, 6, 'g'), cx));
6912        let buffer_len = buffer_1.read(cx).len();
6913        let multibuffer = cx.new_model(|_| MultiBuffer::new(Capability::ReadWrite));
6914        let mut excerpt_1_id = ExcerptId(0);
6915        let mut excerpt_2_id = ExcerptId(0);
6916
6917        multibuffer.update(cx, |multibuffer, cx| {
6918            excerpt_1_id = multibuffer.push_excerpts(
6919                buffer_1.clone(),
6920                [ExcerptRange {
6921                    context: 0..buffer_1.read(cx).len(),
6922                    primary: None,
6923                }],
6924                cx,
6925            )[0];
6926            excerpt_2_id = multibuffer.push_excerpts(
6927                buffer_2.clone(),
6928                [ExcerptRange {
6929                    context: 0..buffer_2.read(cx).len(),
6930                    primary: None,
6931                }],
6932                cx,
6933            )[0];
6934        });
6935
6936        let snapshot = multibuffer.read(cx).snapshot(cx);
6937
6938        let expected_range = snapshot
6939            .anchor_in_excerpt(
6940                excerpt_1_id,
6941                buffer_1.read(cx).anchor_before(buffer_len / 2),
6942            )
6943            .unwrap()
6944            ..snapshot
6945                .anchor_in_excerpt(excerpt_2_id, buffer_2.read(cx).anchor_after(buffer_len / 2))
6946                .unwrap();
6947
6948        let expected_excerpts = vec![
6949            make_expected_excerpt_info(
6950                &snapshot,
6951                cx,
6952                excerpt_1_id,
6953                &buffer_1,
6954                (buffer_len / 2)..buffer_len,
6955            ),
6956            make_expected_excerpt_info(&snapshot, cx, excerpt_2_id, &buffer_2, 0..buffer_len / 2),
6957        ];
6958
6959        let excerpts = snapshot
6960            .excerpts_in_ranges(vec![expected_range.clone()].into_iter())
6961            .map(|(excerpt_id, buffer, actual_range)| {
6962                (
6963                    excerpt_id,
6964                    buffer.remote_id(),
6965                    map_range_from_excerpt(&snapshot, excerpt_id, buffer, actual_range),
6966                )
6967            })
6968            .collect_vec();
6969
6970        validate_excerpts(&excerpts, &expected_excerpts);
6971    }
6972
6973    #[gpui::test]
6974    fn test_excerpts_in_ranges_range_encloses_excerpt(cx: &mut AppContext) {
6975        let buffer_1 = cx.new_model(|cx| Buffer::local(sample_text(6, 6, 'a'), cx));
6976        let buffer_2 = cx.new_model(|cx| Buffer::local(sample_text(6, 6, 'g'), cx));
6977        let buffer_3 = cx.new_model(|cx| Buffer::local(sample_text(6, 6, 'r'), cx));
6978        let buffer_len = buffer_1.read(cx).len();
6979        let multibuffer = cx.new_model(|_| MultiBuffer::new(Capability::ReadWrite));
6980        let mut excerpt_1_id = ExcerptId(0);
6981        let mut excerpt_2_id = ExcerptId(0);
6982        let mut excerpt_3_id = ExcerptId(0);
6983
6984        multibuffer.update(cx, |multibuffer, cx| {
6985            excerpt_1_id = multibuffer.push_excerpts(
6986                buffer_1.clone(),
6987                [ExcerptRange {
6988                    context: 0..buffer_1.read(cx).len(),
6989                    primary: None,
6990                }],
6991                cx,
6992            )[0];
6993            excerpt_2_id = multibuffer.push_excerpts(
6994                buffer_2.clone(),
6995                [ExcerptRange {
6996                    context: 0..buffer_2.read(cx).len(),
6997                    primary: None,
6998                }],
6999                cx,
7000            )[0];
7001            excerpt_3_id = multibuffer.push_excerpts(
7002                buffer_3.clone(),
7003                [ExcerptRange {
7004                    context: 0..buffer_3.read(cx).len(),
7005                    primary: None,
7006                }],
7007                cx,
7008            )[0];
7009        });
7010
7011        let snapshot = multibuffer.read(cx).snapshot(cx);
7012
7013        let expected_range = snapshot
7014            .anchor_in_excerpt(
7015                excerpt_1_id,
7016                buffer_1.read(cx).anchor_before(buffer_len / 2),
7017            )
7018            .unwrap()
7019            ..snapshot
7020                .anchor_in_excerpt(excerpt_3_id, buffer_3.read(cx).anchor_after(buffer_len / 2))
7021                .unwrap();
7022
7023        let expected_excerpts = vec![
7024            make_expected_excerpt_info(
7025                &snapshot,
7026                cx,
7027                excerpt_1_id,
7028                &buffer_1,
7029                (buffer_len / 2)..buffer_len,
7030            ),
7031            make_expected_excerpt_info(&snapshot, cx, excerpt_2_id, &buffer_2, 0..buffer_len),
7032            make_expected_excerpt_info(&snapshot, cx, excerpt_3_id, &buffer_3, 0..buffer_len / 2),
7033        ];
7034
7035        let excerpts = snapshot
7036            .excerpts_in_ranges(vec![expected_range.clone()].into_iter())
7037            .map(|(excerpt_id, buffer, actual_range)| {
7038                (
7039                    excerpt_id,
7040                    buffer.remote_id(),
7041                    map_range_from_excerpt(&snapshot, excerpt_id, buffer, actual_range),
7042                )
7043            })
7044            .collect_vec();
7045
7046        validate_excerpts(&excerpts, &expected_excerpts);
7047    }
7048
7049    #[gpui::test]
7050    fn test_excerpts_in_ranges_multiple_ranges(cx: &mut AppContext) {
7051        let buffer_1 = cx.new_model(|cx| Buffer::local(sample_text(6, 6, 'a'), cx));
7052        let buffer_2 = cx.new_model(|cx| Buffer::local(sample_text(6, 6, 'g'), cx));
7053        let buffer_len = buffer_1.read(cx).len();
7054        let multibuffer = cx.new_model(|_| MultiBuffer::new(Capability::ReadWrite));
7055        let mut excerpt_1_id = ExcerptId(0);
7056        let mut excerpt_2_id = ExcerptId(0);
7057
7058        multibuffer.update(cx, |multibuffer, cx| {
7059            excerpt_1_id = multibuffer.push_excerpts(
7060                buffer_1.clone(),
7061                [ExcerptRange {
7062                    context: 0..buffer_1.read(cx).len(),
7063                    primary: None,
7064                }],
7065                cx,
7066            )[0];
7067            excerpt_2_id = multibuffer.push_excerpts(
7068                buffer_2.clone(),
7069                [ExcerptRange {
7070                    context: 0..buffer_2.read(cx).len(),
7071                    primary: None,
7072                }],
7073                cx,
7074            )[0];
7075        });
7076
7077        let snapshot = multibuffer.read(cx).snapshot(cx);
7078
7079        let ranges = vec![
7080            1..(buffer_len / 4),
7081            (buffer_len / 3)..(buffer_len / 2),
7082            (buffer_len / 4 * 3)..(buffer_len),
7083        ];
7084
7085        let expected_excerpts = ranges
7086            .iter()
7087            .map(|range| {
7088                make_expected_excerpt_info(&snapshot, cx, excerpt_1_id, &buffer_1, range.clone())
7089            })
7090            .collect_vec();
7091
7092        let ranges = ranges.into_iter().map(|range| {
7093            map_range_from_excerpt(
7094                &snapshot,
7095                excerpt_1_id,
7096                &buffer_1.read(cx).snapshot(),
7097                range,
7098            )
7099        });
7100
7101        let excerpts = snapshot
7102            .excerpts_in_ranges(ranges)
7103            .map(|(excerpt_id, buffer, actual_range)| {
7104                (
7105                    excerpt_id,
7106                    buffer.remote_id(),
7107                    map_range_from_excerpt(&snapshot, excerpt_id, buffer, actual_range),
7108                )
7109            })
7110            .collect_vec();
7111
7112        validate_excerpts(&excerpts, &expected_excerpts);
7113    }
7114
7115    #[gpui::test]
7116    fn test_excerpts_in_ranges_range_ends_at_excerpt_end(cx: &mut AppContext) {
7117        let buffer_1 = cx.new_model(|cx| Buffer::local(sample_text(6, 6, 'a'), cx));
7118        let buffer_2 = cx.new_model(|cx| Buffer::local(sample_text(6, 6, 'g'), cx));
7119        let buffer_len = buffer_1.read(cx).len();
7120        let multibuffer = cx.new_model(|_| MultiBuffer::new(Capability::ReadWrite));
7121        let mut excerpt_1_id = ExcerptId(0);
7122        let mut excerpt_2_id = ExcerptId(0);
7123
7124        multibuffer.update(cx, |multibuffer, cx| {
7125            excerpt_1_id = multibuffer.push_excerpts(
7126                buffer_1.clone(),
7127                [ExcerptRange {
7128                    context: 0..buffer_1.read(cx).len(),
7129                    primary: None,
7130                }],
7131                cx,
7132            )[0];
7133            excerpt_2_id = multibuffer.push_excerpts(
7134                buffer_2.clone(),
7135                [ExcerptRange {
7136                    context: 0..buffer_2.read(cx).len(),
7137                    primary: None,
7138                }],
7139                cx,
7140            )[0];
7141        });
7142
7143        let snapshot = multibuffer.read(cx).snapshot(cx);
7144
7145        let ranges = [0..buffer_len, (buffer_len / 3)..(buffer_len / 2)];
7146
7147        let expected_excerpts = vec![
7148            make_expected_excerpt_info(&snapshot, cx, excerpt_1_id, &buffer_1, ranges[0].clone()),
7149            make_expected_excerpt_info(&snapshot, cx, excerpt_2_id, &buffer_2, ranges[1].clone()),
7150        ];
7151
7152        let ranges = [
7153            map_range_from_excerpt(
7154                &snapshot,
7155                excerpt_1_id,
7156                &buffer_1.read(cx).snapshot(),
7157                ranges[0].clone(),
7158            ),
7159            map_range_from_excerpt(
7160                &snapshot,
7161                excerpt_2_id,
7162                &buffer_2.read(cx).snapshot(),
7163                ranges[1].clone(),
7164            ),
7165        ];
7166
7167        let excerpts = snapshot
7168            .excerpts_in_ranges(ranges.into_iter())
7169            .map(|(excerpt_id, buffer, actual_range)| {
7170                (
7171                    excerpt_id,
7172                    buffer.remote_id(),
7173                    map_range_from_excerpt(&snapshot, excerpt_id, buffer, actual_range),
7174                )
7175            })
7176            .collect_vec();
7177
7178        validate_excerpts(&excerpts, &expected_excerpts);
7179    }
7180
7181    #[gpui::test]
7182    fn test_split_ranges(cx: &mut AppContext) {
7183        let buffer_1 = cx.new_model(|cx| Buffer::local(sample_text(6, 6, 'a'), cx));
7184        let buffer_2 = cx.new_model(|cx| Buffer::local(sample_text(6, 6, 'g'), cx));
7185        let multibuffer = cx.new_model(|_| MultiBuffer::new(Capability::ReadWrite));
7186        multibuffer.update(cx, |multibuffer, cx| {
7187            multibuffer.push_excerpts(
7188                buffer_1.clone(),
7189                [ExcerptRange {
7190                    context: 0..buffer_1.read(cx).len(),
7191                    primary: None,
7192                }],
7193                cx,
7194            );
7195            multibuffer.push_excerpts(
7196                buffer_2.clone(),
7197                [ExcerptRange {
7198                    context: 0..buffer_2.read(cx).len(),
7199                    primary: None,
7200                }],
7201                cx,
7202            );
7203        });
7204
7205        let snapshot = multibuffer.read(cx).snapshot(cx);
7206
7207        let buffer_1_len = buffer_1.read(cx).len();
7208        let buffer_2_len = buffer_2.read(cx).len();
7209        let buffer_1_midpoint = buffer_1_len / 2;
7210        let buffer_2_start = buffer_1_len + '\n'.len_utf8();
7211        let buffer_2_midpoint = buffer_2_start + buffer_2_len / 2;
7212        let total_len = buffer_2_start + buffer_2_len;
7213
7214        let input_ranges = [
7215            0..buffer_1_midpoint,
7216            buffer_1_midpoint..buffer_2_midpoint,
7217            buffer_2_midpoint..total_len,
7218        ]
7219        .map(|range| snapshot.anchor_before(range.start)..snapshot.anchor_after(range.end));
7220
7221        let actual_ranges = snapshot
7222            .split_ranges(input_ranges.into_iter())
7223            .map(|range| range.to_offset(&snapshot))
7224            .collect::<Vec<_>>();
7225
7226        let expected_ranges = vec![
7227            0..buffer_1_midpoint,
7228            buffer_1_midpoint..buffer_1_len,
7229            buffer_2_start..buffer_2_midpoint,
7230            buffer_2_midpoint..total_len,
7231        ];
7232
7233        assert_eq!(actual_ranges, expected_ranges);
7234    }
7235
7236    #[gpui::test]
7237    fn test_split_ranges_single_range_spanning_three_excerpts(cx: &mut AppContext) {
7238        let buffer_1 = cx.new_model(|cx| Buffer::local(sample_text(6, 6, 'a'), cx));
7239        let buffer_2 = cx.new_model(|cx| Buffer::local(sample_text(6, 6, 'g'), cx));
7240        let buffer_3 = cx.new_model(|cx| Buffer::local(sample_text(6, 6, 'm'), cx));
7241        let multibuffer = cx.new_model(|_| MultiBuffer::new(Capability::ReadWrite));
7242        multibuffer.update(cx, |multibuffer, cx| {
7243            multibuffer.push_excerpts(
7244                buffer_1.clone(),
7245                [ExcerptRange {
7246                    context: 0..buffer_1.read(cx).len(),
7247                    primary: None,
7248                }],
7249                cx,
7250            );
7251            multibuffer.push_excerpts(
7252                buffer_2.clone(),
7253                [ExcerptRange {
7254                    context: 0..buffer_2.read(cx).len(),
7255                    primary: None,
7256                }],
7257                cx,
7258            );
7259            multibuffer.push_excerpts(
7260                buffer_3.clone(),
7261                [ExcerptRange {
7262                    context: 0..buffer_3.read(cx).len(),
7263                    primary: None,
7264                }],
7265                cx,
7266            );
7267        });
7268
7269        let snapshot = multibuffer.read(cx).snapshot(cx);
7270
7271        let buffer_1_len = buffer_1.read(cx).len();
7272        let buffer_2_len = buffer_2.read(cx).len();
7273        let buffer_3_len = buffer_3.read(cx).len();
7274        let buffer_2_start = buffer_1_len + '\n'.len_utf8();
7275        let buffer_3_start = buffer_2_start + buffer_2_len + '\n'.len_utf8();
7276        let buffer_1_midpoint = buffer_1_len / 2;
7277        let buffer_3_midpoint = buffer_3_start + buffer_3_len / 2;
7278
7279        let input_range =
7280            snapshot.anchor_before(buffer_1_midpoint)..snapshot.anchor_after(buffer_3_midpoint);
7281
7282        let actual_ranges = snapshot
7283            .split_ranges(std::iter::once(input_range))
7284            .map(|range| range.to_offset(&snapshot))
7285            .collect::<Vec<_>>();
7286
7287        let expected_ranges = vec![
7288            buffer_1_midpoint..buffer_1_len,
7289            buffer_2_start..buffer_2_start + buffer_2_len,
7290            buffer_3_start..buffer_3_midpoint,
7291        ];
7292
7293        assert_eq!(actual_ranges, expected_ranges);
7294    }
7295}