multi_buffer.rs

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