multi_buffer.rs

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