multi_buffer.rs

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