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