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