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