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