multi_buffer.rs

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