multi_buffer.rs

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