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