multi_buffer.rs

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