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