multi_buffer.rs

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