multi_buffer.rs

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