multi_buffer.rs

   1mod anchor;
   2#[cfg(test)]
   3mod multi_buffer_tests;
   4
   5pub use anchor::{Anchor, AnchorRangeExt, Offset};
   6use anyhow::{anyhow, Result};
   7use clock::ReplicaId;
   8use collections::{BTreeMap, Bound, HashMap, HashSet};
   9use futures::{channel::mpsc, SinkExt};
  10use gpui::{AppContext, EntityId, EventEmitter, Model, ModelContext, Task};
  11use itertools::Itertools;
  12use language::{
  13    language_settings::{language_settings, LanguageSettings},
  14    AutoindentMode, Buffer, BufferChunks, BufferRow, BufferSnapshot, Capability, CharClassifier,
  15    CharKind, Chunk, CursorShape, DiagnosticEntry, DiskState, File, IndentGuide, IndentSize,
  16    Language, LanguageScope, OffsetRangeExt, OffsetUtf16, Outline, OutlineItem, Point, PointUtf16,
  17    Selection, TextDimension, ToOffset as _, ToOffsetUtf16 as _, ToPoint as _, ToPointUtf16 as _,
  18    TransactionId, Unclipped,
  19};
  20use smallvec::SmallVec;
  21use std::{
  22    any::type_name,
  23    borrow::Cow,
  24    cell::{Ref, RefCell},
  25    cmp, fmt,
  26    future::Future,
  27    io,
  28    iter::{self, FromIterator},
  29    mem,
  30    ops::{Range, RangeBounds, Sub},
  31    str,
  32    sync::Arc,
  33    time::{Duration, Instant},
  34};
  35use sum_tree::{Bias, Cursor, SumTree};
  36use text::{
  37    locator::Locator,
  38    subscription::{Subscription, Topic},
  39    BufferId, Edit, TextSummary,
  40};
  41use theme::SyntaxTheme;
  42
  43use util::post_inc;
  44
  45#[cfg(any(test, feature = "test-support"))]
  46use gpui::Context;
  47
  48const NEWLINES: &[u8] = &[b'\n'; u8::MAX as usize];
  49
  50#[derive(Debug, Default, Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)]
  51pub struct ExcerptId(usize);
  52
  53impl From<ExcerptId> for EntityId {
  54    fn from(id: ExcerptId) -> Self {
  55        EntityId::from(id.0 as u64)
  56    }
  57}
  58
  59/// One or more [`Buffers`](Buffer) being edited in a single view.
  60///
  61/// See <https://zed.dev/features#multi-buffers>
  62pub struct MultiBuffer {
  63    /// A snapshot of the [`Excerpt`]s in the MultiBuffer.
  64    /// Use [`MultiBuffer::snapshot`] to get a up-to-date snapshot.
  65    snapshot: RefCell<MultiBufferSnapshot>,
  66    /// Contains the state of the buffers being edited
  67    buffers: RefCell<HashMap<BufferId, BufferState>>,
  68    subscriptions: Topic,
  69    /// If true, the multi-buffer only contains a single [`Buffer`] and a single [`Excerpt`]
  70    singleton: bool,
  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        edited_buffer: Option<Model<Buffer>>,
  95    },
  96    TransactionUndone {
  97        transaction_id: TransactionId,
  98    },
  99    Reloaded,
 100    ReloadNeeded,
 101
 102    LanguageChanged(BufferId),
 103    CapabilityChanged,
 104    Reparsed(BufferId),
 105    Saved,
 106    FileHandleChanged,
 107    Closed,
 108    Discarded,
 109    DirtyChanged,
 110    DiagnosticsUpdated,
 111}
 112
 113/// A diff hunk, representing a range of consequent lines in a multibuffer.
 114#[derive(Debug, Clone, PartialEq, Eq)]
 115pub struct MultiBufferDiffHunk {
 116    /// The row range in the multibuffer where this diff hunk appears.
 117    pub row_range: Range<MultiBufferRow>,
 118    /// The buffer ID that this hunk belongs to.
 119    pub buffer_id: BufferId,
 120    /// The range of the underlying buffer that this hunk corresponds to.
 121    pub buffer_range: Range<text::Anchor>,
 122    /// The range within the buffer's diff base that this hunk corresponds to.
 123    pub diff_base_byte_range: Range<usize>,
 124}
 125
 126pub type MultiBufferPoint = Point;
 127
 128#[derive(Copy, Clone, Debug, Default, Eq, Ord, PartialOrd, PartialEq, Hash, serde::Deserialize)]
 129#[serde(transparent)]
 130pub struct MultiBufferRow(pub u32);
 131
 132impl MultiBufferRow {
 133    pub const MIN: Self = Self(0);
 134    pub const MAX: Self = Self(u32::MAX);
 135}
 136
 137#[derive(Clone)]
 138struct History {
 139    next_transaction_id: TransactionId,
 140    undo_stack: Vec<Transaction>,
 141    redo_stack: Vec<Transaction>,
 142    transaction_depth: usize,
 143    group_interval: Duration,
 144}
 145
 146#[derive(Clone)]
 147struct Transaction {
 148    id: TransactionId,
 149    buffer_transactions: HashMap<BufferId, text::TransactionId>,
 150    first_edit_at: Instant,
 151    last_edit_at: Instant,
 152    suppress_grouping: bool,
 153}
 154
 155pub trait ToOffset: 'static + fmt::Debug {
 156    fn to_offset(&self, snapshot: &MultiBufferSnapshot) -> usize;
 157}
 158
 159pub trait ToOffsetUtf16: 'static + fmt::Debug {
 160    fn to_offset_utf16(&self, snapshot: &MultiBufferSnapshot) -> OffsetUtf16;
 161}
 162
 163pub trait ToPoint: 'static + fmt::Debug {
 164    fn to_point(&self, snapshot: &MultiBufferSnapshot) -> Point;
 165}
 166
 167pub trait ToPointUtf16: 'static + fmt::Debug {
 168    fn to_point_utf16(&self, snapshot: &MultiBufferSnapshot) -> PointUtf16;
 169}
 170
 171struct BufferState {
 172    buffer: Model<Buffer>,
 173    last_version: clock::Global,
 174    last_non_text_state_update_count: usize,
 175    excerpts: Vec<Locator>,
 176    _subscriptions: [gpui::Subscription; 2],
 177}
 178
 179/// The contents of a [`MultiBuffer`] at a single point in time.
 180#[derive(Clone, Default)]
 181pub struct MultiBufferSnapshot {
 182    singleton: bool,
 183    excerpts: SumTree<Excerpt>,
 184    excerpt_ids: SumTree<ExcerptIdMapping>,
 185    trailing_excerpt_update_count: usize,
 186    non_text_state_update_count: usize,
 187    edit_count: usize,
 188    is_dirty: bool,
 189    has_deleted_file: bool,
 190    has_conflict: bool,
 191    show_headers: bool,
 192}
 193
 194#[derive(Clone)]
 195pub struct ExcerptInfo {
 196    pub id: ExcerptId,
 197    pub buffer: BufferSnapshot,
 198    pub buffer_id: BufferId,
 199    pub range: ExcerptRange<text::Anchor>,
 200    pub text_summary: TextSummary,
 201}
 202
 203impl std::fmt::Debug for ExcerptInfo {
 204    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 205        f.debug_struct(type_name::<Self>())
 206            .field("id", &self.id)
 207            .field("buffer_id", &self.buffer_id)
 208            .field("path", &self.buffer.file().map(|f| f.path()))
 209            .field("range", &self.range)
 210            .finish()
 211    }
 212}
 213
 214/// A boundary between [`Excerpt`]s in a [`MultiBuffer`]
 215#[derive(Debug)]
 216pub struct ExcerptBoundary {
 217    pub prev: Option<ExcerptInfo>,
 218    pub next: Option<ExcerptInfo>,
 219    /// The row in the `MultiBuffer` where the boundary is located
 220    pub row: MultiBufferRow,
 221}
 222
 223impl ExcerptBoundary {
 224    pub fn starts_new_buffer(&self) -> bool {
 225        match (self.prev.as_ref(), self.next.as_ref()) {
 226            (None, _) => true,
 227            (Some(_), None) => false,
 228            (Some(prev), Some(next)) => prev.buffer_id != next.buffer_id,
 229        }
 230    }
 231}
 232
 233/// A slice into a [`Buffer`] that is being edited in a [`MultiBuffer`].
 234#[derive(Clone)]
 235struct Excerpt {
 236    /// The unique identifier for this excerpt
 237    id: ExcerptId,
 238    /// The location of the excerpt in the [`MultiBuffer`]
 239    locator: Locator,
 240    /// The buffer being excerpted
 241    buffer_id: BufferId,
 242    /// A snapshot of the buffer being excerpted
 243    buffer: BufferSnapshot,
 244    /// The range of the buffer to be shown in the excerpt
 245    range: ExcerptRange<text::Anchor>,
 246    /// The last row in the excerpted slice of the buffer
 247    max_buffer_row: BufferRow,
 248    /// A summary of the text in the excerpt
 249    text_summary: TextSummary,
 250    has_trailing_newline: bool,
 251}
 252
 253/// A public view into an [`Excerpt`] in a [`MultiBuffer`].
 254///
 255/// Contains methods for getting the [`Buffer`] of the excerpt,
 256/// as well as mapping offsets to/from buffer and multibuffer coordinates.
 257#[derive(Clone)]
 258pub struct MultiBufferExcerpt<'a> {
 259    excerpt: &'a Excerpt,
 260    excerpt_offset: usize,
 261    excerpt_position: Point,
 262}
 263
 264#[derive(Clone, Debug)]
 265struct ExcerptIdMapping {
 266    id: ExcerptId,
 267    locator: Locator,
 268}
 269
 270/// A range of text from a single [`Buffer`], to be shown as an [`Excerpt`].
 271/// These ranges are relative to the buffer itself
 272#[derive(Clone, Debug, Eq, PartialEq, Hash)]
 273pub struct ExcerptRange<T> {
 274    /// The full range of text to be shown in the excerpt.
 275    pub context: Range<T>,
 276    /// The primary range of text to be highlighted in the excerpt.
 277    /// In a multi-buffer search, this would be the text that matched the search
 278    pub primary: Option<Range<T>>,
 279}
 280
 281#[derive(Clone, Debug, Default)]
 282pub struct ExcerptSummary {
 283    excerpt_id: ExcerptId,
 284    /// The location of the last [`Excerpt`] being summarized
 285    excerpt_locator: Locator,
 286    widest_line_number: u32,
 287    text: TextSummary,
 288}
 289
 290#[derive(Clone)]
 291pub struct MultiBufferRows<'a> {
 292    buffer_row_range: Range<u32>,
 293    excerpts: Cursor<'a, Excerpt, Point>,
 294}
 295
 296pub struct MultiBufferChunks<'a> {
 297    range: Range<usize>,
 298    excerpts: Cursor<'a, Excerpt, usize>,
 299    excerpt_chunks: Option<ExcerptChunks<'a>>,
 300    language_aware: bool,
 301}
 302
 303pub struct MultiBufferBytes<'a> {
 304    range: Range<usize>,
 305    excerpts: Cursor<'a, Excerpt, usize>,
 306    excerpt_bytes: Option<ExcerptBytes<'a>>,
 307    chunk: &'a [u8],
 308}
 309
 310pub struct ReversedMultiBufferBytes<'a> {
 311    range: Range<usize>,
 312    excerpts: Cursor<'a, Excerpt, usize>,
 313    excerpt_bytes: Option<ExcerptBytes<'a>>,
 314    chunk: &'a [u8],
 315}
 316
 317struct ExcerptChunks<'a> {
 318    excerpt_id: ExcerptId,
 319    content_chunks: BufferChunks<'a>,
 320    footer_height: usize,
 321}
 322
 323struct ExcerptBytes<'a> {
 324    content_bytes: text::Bytes<'a>,
 325    padding_height: usize,
 326    reversed: bool,
 327}
 328
 329struct BufferEdit {
 330    range: Range<usize>,
 331    new_text: Arc<str>,
 332    is_insertion: bool,
 333    original_indent_column: u32,
 334}
 335
 336#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
 337pub enum ExpandExcerptDirection {
 338    Up,
 339    Down,
 340    UpAndDown,
 341}
 342
 343impl ExpandExcerptDirection {
 344    pub fn should_expand_up(&self) -> bool {
 345        match self {
 346            ExpandExcerptDirection::Up => true,
 347            ExpandExcerptDirection::Down => false,
 348            ExpandExcerptDirection::UpAndDown => true,
 349        }
 350    }
 351
 352    pub fn should_expand_down(&self) -> bool {
 353        match self {
 354            ExpandExcerptDirection::Up => false,
 355            ExpandExcerptDirection::Down => true,
 356            ExpandExcerptDirection::UpAndDown => true,
 357        }
 358    }
 359}
 360
 361#[derive(Clone, Debug, PartialEq)]
 362pub struct MultiBufferIndentGuide {
 363    pub multibuffer_row_range: Range<MultiBufferRow>,
 364    pub buffer: IndentGuide,
 365}
 366
 367impl std::ops::Deref for MultiBufferIndentGuide {
 368    type Target = IndentGuide;
 369
 370    fn deref(&self) -> &Self::Target {
 371        &self.buffer
 372    }
 373}
 374
 375impl MultiBuffer {
 376    pub fn new(capability: Capability) -> Self {
 377        Self {
 378            snapshot: RefCell::new(MultiBufferSnapshot {
 379                show_headers: true,
 380                ..MultiBufferSnapshot::default()
 381            }),
 382            buffers: RefCell::default(),
 383            subscriptions: Topic::default(),
 384            singleton: false,
 385            capability,
 386            title: None,
 387            history: History {
 388                next_transaction_id: clock::Lamport::default(),
 389                undo_stack: Vec::new(),
 390                redo_stack: Vec::new(),
 391                transaction_depth: 0,
 392                group_interval: Duration::from_millis(300),
 393            },
 394        }
 395    }
 396
 397    pub fn without_headers(capability: Capability) -> Self {
 398        Self {
 399            snapshot: Default::default(),
 400            buffers: Default::default(),
 401            subscriptions: Default::default(),
 402            singleton: false,
 403            capability,
 404            history: History {
 405                next_transaction_id: Default::default(),
 406                undo_stack: Default::default(),
 407                redo_stack: Default::default(),
 408                transaction_depth: 0,
 409                group_interval: Duration::from_millis(300),
 410            },
 411            title: Default::default(),
 412        }
 413    }
 414
 415    pub fn clone(&self, new_cx: &mut ModelContext<Self>) -> Self {
 416        let mut buffers = HashMap::default();
 417        for (buffer_id, buffer_state) in self.buffers.borrow().iter() {
 418            buffers.insert(
 419                *buffer_id,
 420                BufferState {
 421                    buffer: buffer_state.buffer.clone(),
 422                    last_version: buffer_state.last_version.clone(),
 423                    last_non_text_state_update_count: buffer_state.last_non_text_state_update_count,
 424                    excerpts: buffer_state.excerpts.clone(),
 425                    _subscriptions: [
 426                        new_cx.observe(&buffer_state.buffer, |_, _, cx| cx.notify()),
 427                        new_cx.subscribe(&buffer_state.buffer, Self::on_buffer_event),
 428                    ],
 429                },
 430            );
 431        }
 432        Self {
 433            snapshot: RefCell::new(self.snapshot.borrow().clone()),
 434            buffers: RefCell::new(buffers),
 435            subscriptions: Default::default(),
 436            singleton: self.singleton,
 437            capability: self.capability,
 438            history: self.history.clone(),
 439            title: self.title.clone(),
 440        }
 441    }
 442
 443    pub fn with_title(mut self, title: String) -> Self {
 444        self.title = Some(title);
 445        self
 446    }
 447
 448    pub fn read_only(&self) -> bool {
 449        self.capability == Capability::ReadOnly
 450    }
 451
 452    pub fn singleton(buffer: Model<Buffer>, cx: &mut ModelContext<Self>) -> Self {
 453        let mut this = Self::new(buffer.read(cx).capability());
 454        this.singleton = true;
 455        this.push_excerpts(
 456            buffer,
 457            [ExcerptRange {
 458                context: text::Anchor::MIN..text::Anchor::MAX,
 459                primary: None,
 460            }],
 461            cx,
 462        );
 463        this.snapshot.borrow_mut().singleton = true;
 464        this
 465    }
 466
 467    /// Returns an up-to-date snapshot of the MultiBuffer.
 468    pub fn snapshot(&self, cx: &AppContext) -> MultiBufferSnapshot {
 469        self.sync(cx);
 470        self.snapshot.borrow().clone()
 471    }
 472
 473    pub fn read(&self, cx: &AppContext) -> Ref<MultiBufferSnapshot> {
 474        self.sync(cx);
 475        self.snapshot.borrow()
 476    }
 477
 478    pub fn as_singleton(&self) -> Option<Model<Buffer>> {
 479        if self.singleton {
 480            return Some(
 481                self.buffers
 482                    .borrow()
 483                    .values()
 484                    .next()
 485                    .unwrap()
 486                    .buffer
 487                    .clone(),
 488            );
 489        } else {
 490            None
 491        }
 492    }
 493
 494    pub fn is_singleton(&self) -> bool {
 495        self.singleton
 496    }
 497
 498    pub fn subscribe(&mut self) -> Subscription {
 499        self.subscriptions.subscribe()
 500    }
 501
 502    pub fn is_dirty(&self, cx: &AppContext) -> bool {
 503        self.read(cx).is_dirty()
 504    }
 505
 506    pub fn has_deleted_file(&self, cx: &AppContext) -> bool {
 507        self.read(cx).has_deleted_file()
 508    }
 509
 510    pub fn has_conflict(&self, cx: &AppContext) -> bool {
 511        self.read(cx).has_conflict()
 512    }
 513
 514    // The `is_empty` signature doesn't match what clippy expects
 515    #[allow(clippy::len_without_is_empty)]
 516    pub fn len(&self, cx: &AppContext) -> usize {
 517        self.read(cx).len()
 518    }
 519
 520    pub fn is_empty(&self, cx: &AppContext) -> bool {
 521        self.len(cx) != 0
 522    }
 523
 524    pub fn symbols_containing<T: ToOffset>(
 525        &self,
 526        offset: T,
 527        theme: Option<&SyntaxTheme>,
 528        cx: &AppContext,
 529    ) -> Option<(BufferId, Vec<OutlineItem<Anchor>>)> {
 530        self.read(cx).symbols_containing(offset, theme)
 531    }
 532
 533    pub fn edit<I, S, T>(
 534        &self,
 535        edits: I,
 536        autoindent_mode: Option<AutoindentMode>,
 537        cx: &mut ModelContext<Self>,
 538    ) where
 539        I: IntoIterator<Item = (Range<S>, T)>,
 540        S: ToOffset,
 541        T: Into<Arc<str>>,
 542    {
 543        let snapshot = self.read(cx);
 544        let edits = edits
 545            .into_iter()
 546            .map(|(range, new_text)| {
 547                let mut range = range.start.to_offset(&snapshot)..range.end.to_offset(&snapshot);
 548                if range.start > range.end {
 549                    mem::swap(&mut range.start, &mut range.end);
 550                }
 551                (range, new_text.into())
 552            })
 553            .collect::<Vec<_>>();
 554
 555        return edit_internal(self, snapshot, edits, autoindent_mode, cx);
 556
 557        // Non-generic part of edit, hoisted out to avoid blowing up LLVM IR.
 558        fn edit_internal(
 559            this: &MultiBuffer,
 560            snapshot: Ref<MultiBufferSnapshot>,
 561            edits: Vec<(Range<usize>, Arc<str>)>,
 562            mut autoindent_mode: Option<AutoindentMode>,
 563            cx: &mut ModelContext<MultiBuffer>,
 564        ) {
 565            if this.read_only() || this.buffers.borrow().is_empty() {
 566                return;
 567            }
 568
 569            if let Some(buffer) = this.as_singleton() {
 570                buffer.update(cx, |buffer, cx| {
 571                    buffer.edit(edits, autoindent_mode, cx);
 572                });
 573                cx.emit(Event::ExcerptsEdited {
 574                    ids: this.excerpt_ids(),
 575                });
 576                return;
 577            }
 578
 579            let original_indent_columns = match &mut autoindent_mode {
 580                Some(AutoindentMode::Block {
 581                    original_indent_columns,
 582                }) => mem::take(original_indent_columns),
 583                _ => Default::default(),
 584            };
 585
 586            let (buffer_edits, edited_excerpt_ids) =
 587                this.convert_edits_to_buffer_edits(edits, &snapshot, &original_indent_columns);
 588            drop(snapshot);
 589
 590            for (buffer_id, mut edits) in buffer_edits {
 591                edits.sort_unstable_by_key(|edit| edit.range.start);
 592                this.buffers.borrow()[&buffer_id]
 593                    .buffer
 594                    .update(cx, |buffer, cx| {
 595                        let mut edits = edits.into_iter().peekable();
 596                        let mut insertions = Vec::new();
 597                        let mut original_indent_columns = Vec::new();
 598                        let mut deletions = Vec::new();
 599                        let empty_str: Arc<str> = Arc::default();
 600                        while let Some(BufferEdit {
 601                            mut range,
 602                            new_text,
 603                            mut is_insertion,
 604                            original_indent_column,
 605                        }) = edits.next()
 606                        {
 607                            while let Some(BufferEdit {
 608                                range: next_range,
 609                                is_insertion: next_is_insertion,
 610                                ..
 611                            }) = edits.peek()
 612                            {
 613                                if range.end >= next_range.start {
 614                                    range.end = cmp::max(next_range.end, range.end);
 615                                    is_insertion |= *next_is_insertion;
 616                                    edits.next();
 617                                } else {
 618                                    break;
 619                                }
 620                            }
 621
 622                            if is_insertion {
 623                                original_indent_columns.push(original_indent_column);
 624                                insertions.push((
 625                                    buffer.anchor_before(range.start)
 626                                        ..buffer.anchor_before(range.end),
 627                                    new_text.clone(),
 628                                ));
 629                            } else if !range.is_empty() {
 630                                deletions.push((
 631                                    buffer.anchor_before(range.start)
 632                                        ..buffer.anchor_before(range.end),
 633                                    empty_str.clone(),
 634                                ));
 635                            }
 636                        }
 637
 638                        let deletion_autoindent_mode =
 639                            if let Some(AutoindentMode::Block { .. }) = autoindent_mode {
 640                                Some(AutoindentMode::Block {
 641                                    original_indent_columns: Default::default(),
 642                                })
 643                            } else {
 644                                autoindent_mode.clone()
 645                            };
 646                        let insertion_autoindent_mode =
 647                            if let Some(AutoindentMode::Block { .. }) = autoindent_mode {
 648                                Some(AutoindentMode::Block {
 649                                    original_indent_columns,
 650                                })
 651                            } else {
 652                                autoindent_mode.clone()
 653                            };
 654
 655                        buffer.edit(deletions, deletion_autoindent_mode, cx);
 656                        buffer.edit(insertions, insertion_autoindent_mode, cx);
 657                    })
 658            }
 659
 660            cx.emit(Event::ExcerptsEdited {
 661                ids: edited_excerpt_ids,
 662            });
 663        }
 664    }
 665
 666    fn convert_edits_to_buffer_edits(
 667        &self,
 668        edits: Vec<(Range<usize>, Arc<str>)>,
 669        snapshot: &MultiBufferSnapshot,
 670        original_indent_columns: &[u32],
 671    ) -> (HashMap<BufferId, Vec<BufferEdit>>, Vec<ExcerptId>) {
 672        let mut buffer_edits: HashMap<BufferId, Vec<BufferEdit>> = Default::default();
 673        let mut edited_excerpt_ids = Vec::new();
 674        let mut cursor = snapshot.excerpts.cursor::<usize>(&());
 675        for (ix, (range, new_text)) in edits.into_iter().enumerate() {
 676            let original_indent_column = original_indent_columns.get(ix).copied().unwrap_or(0);
 677            cursor.seek(&range.start, Bias::Right, &());
 678            if cursor.item().is_none() && range.start == *cursor.start() {
 679                cursor.prev(&());
 680            }
 681            let start_excerpt = cursor.item().expect("start offset out of bounds");
 682            let start_overshoot = range.start - cursor.start();
 683            let buffer_start = start_excerpt
 684                .range
 685                .context
 686                .start
 687                .to_offset(&start_excerpt.buffer)
 688                + start_overshoot;
 689            edited_excerpt_ids.push(start_excerpt.id);
 690
 691            cursor.seek(&range.end, Bias::Right, &());
 692            if cursor.item().is_none() && range.end == *cursor.start() {
 693                cursor.prev(&());
 694            }
 695            let end_excerpt = cursor.item().expect("end offset out of bounds");
 696            let end_overshoot = range.end - cursor.start();
 697            let buffer_end = end_excerpt
 698                .range
 699                .context
 700                .start
 701                .to_offset(&end_excerpt.buffer)
 702                + end_overshoot;
 703
 704            if start_excerpt.id == end_excerpt.id {
 705                buffer_edits
 706                    .entry(start_excerpt.buffer_id)
 707                    .or_default()
 708                    .push(BufferEdit {
 709                        range: buffer_start..buffer_end,
 710                        new_text,
 711                        is_insertion: true,
 712                        original_indent_column,
 713                    });
 714            } else {
 715                edited_excerpt_ids.push(end_excerpt.id);
 716                let start_excerpt_range = buffer_start
 717                    ..start_excerpt
 718                        .range
 719                        .context
 720                        .end
 721                        .to_offset(&start_excerpt.buffer);
 722                let end_excerpt_range = end_excerpt
 723                    .range
 724                    .context
 725                    .start
 726                    .to_offset(&end_excerpt.buffer)
 727                    ..buffer_end;
 728                buffer_edits
 729                    .entry(start_excerpt.buffer_id)
 730                    .or_default()
 731                    .push(BufferEdit {
 732                        range: start_excerpt_range,
 733                        new_text: new_text.clone(),
 734                        is_insertion: true,
 735                        original_indent_column,
 736                    });
 737                buffer_edits
 738                    .entry(end_excerpt.buffer_id)
 739                    .or_default()
 740                    .push(BufferEdit {
 741                        range: end_excerpt_range,
 742                        new_text: new_text.clone(),
 743                        is_insertion: false,
 744                        original_indent_column,
 745                    });
 746
 747                cursor.seek(&range.start, Bias::Right, &());
 748                cursor.next(&());
 749                while let Some(excerpt) = cursor.item() {
 750                    if excerpt.id == end_excerpt.id {
 751                        break;
 752                    }
 753                    buffer_edits
 754                        .entry(excerpt.buffer_id)
 755                        .or_default()
 756                        .push(BufferEdit {
 757                            range: excerpt.range.context.to_offset(&excerpt.buffer),
 758                            new_text: new_text.clone(),
 759                            is_insertion: false,
 760                            original_indent_column,
 761                        });
 762                    edited_excerpt_ids.push(excerpt.id);
 763                    cursor.next(&());
 764                }
 765            }
 766        }
 767        (buffer_edits, edited_excerpt_ids)
 768    }
 769
 770    pub fn autoindent_ranges<I, S>(&self, ranges: I, cx: &mut ModelContext<Self>)
 771    where
 772        I: IntoIterator<Item = Range<S>>,
 773        S: ToOffset,
 774    {
 775        let snapshot = self.read(cx);
 776        let empty = Arc::<str>::from("");
 777        let edits = ranges
 778            .into_iter()
 779            .map(|range| {
 780                let mut range = range.start.to_offset(&snapshot)..range.end.to_offset(&snapshot);
 781                if range.start > range.end {
 782                    mem::swap(&mut range.start, &mut range.end);
 783                }
 784                (range, empty.clone())
 785            })
 786            .collect::<Vec<_>>();
 787
 788        return autoindent_ranges_internal(self, snapshot, edits, cx);
 789
 790        fn autoindent_ranges_internal(
 791            this: &MultiBuffer,
 792            snapshot: Ref<MultiBufferSnapshot>,
 793            edits: Vec<(Range<usize>, Arc<str>)>,
 794            cx: &mut ModelContext<MultiBuffer>,
 795        ) {
 796            if this.read_only() || this.buffers.borrow().is_empty() {
 797                return;
 798            }
 799
 800            if let Some(buffer) = this.as_singleton() {
 801                buffer.update(cx, |buffer, cx| {
 802                    buffer.autoindent_ranges(edits.into_iter().map(|e| e.0), cx);
 803                });
 804                cx.emit(Event::ExcerptsEdited {
 805                    ids: this.excerpt_ids(),
 806                });
 807                return;
 808            }
 809
 810            let (buffer_edits, edited_excerpt_ids) =
 811                this.convert_edits_to_buffer_edits(edits, &snapshot, &[]);
 812            drop(snapshot);
 813
 814            for (buffer_id, mut edits) in buffer_edits {
 815                edits.sort_unstable_by_key(|edit| edit.range.start);
 816
 817                let mut ranges: Vec<Range<usize>> = Vec::new();
 818                for edit in edits {
 819                    if let Some(last_range) = ranges.last_mut() {
 820                        if edit.range.start <= last_range.end {
 821                            last_range.end = last_range.end.max(edit.range.end);
 822                            continue;
 823                        }
 824                    }
 825                    ranges.push(edit.range);
 826                }
 827
 828                this.buffers.borrow()[&buffer_id]
 829                    .buffer
 830                    .update(cx, |buffer, cx| {
 831                        buffer.autoindent_ranges(ranges, cx);
 832                    })
 833            }
 834
 835            cx.emit(Event::ExcerptsEdited {
 836                ids: edited_excerpt_ids,
 837            });
 838        }
 839    }
 840
 841    // Inserts newlines at the given position to create an empty line, returning the start of the new line.
 842    // You can also request the insertion of empty lines above and below the line starting at the returned point.
 843    // Panics if the given position is invalid.
 844    pub fn insert_empty_line(
 845        &mut self,
 846        position: impl ToPoint,
 847        space_above: bool,
 848        space_below: bool,
 849        cx: &mut ModelContext<Self>,
 850    ) -> Point {
 851        let multibuffer_point = position.to_point(&self.read(cx));
 852        if let Some(buffer) = self.as_singleton() {
 853            buffer.update(cx, |buffer, cx| {
 854                buffer.insert_empty_line(multibuffer_point, space_above, space_below, cx)
 855            })
 856        } else {
 857            let (buffer, buffer_point, _) =
 858                self.point_to_buffer_point(multibuffer_point, cx).unwrap();
 859            self.start_transaction(cx);
 860            let empty_line_start = buffer.update(cx, |buffer, cx| {
 861                buffer.insert_empty_line(buffer_point, space_above, space_below, cx)
 862            });
 863            self.end_transaction(cx);
 864            multibuffer_point + (empty_line_start - buffer_point)
 865        }
 866    }
 867
 868    pub fn start_transaction(&mut self, cx: &mut ModelContext<Self>) -> Option<TransactionId> {
 869        self.start_transaction_at(Instant::now(), cx)
 870    }
 871
 872    pub fn start_transaction_at(
 873        &mut self,
 874        now: Instant,
 875        cx: &mut ModelContext<Self>,
 876    ) -> Option<TransactionId> {
 877        if let Some(buffer) = self.as_singleton() {
 878            return buffer.update(cx, |buffer, _| buffer.start_transaction_at(now));
 879        }
 880
 881        for BufferState { buffer, .. } in self.buffers.borrow().values() {
 882            buffer.update(cx, |buffer, _| buffer.start_transaction_at(now));
 883        }
 884        self.history.start_transaction(now)
 885    }
 886
 887    pub fn end_transaction(&mut self, cx: &mut ModelContext<Self>) -> Option<TransactionId> {
 888        self.end_transaction_at(Instant::now(), cx)
 889    }
 890
 891    pub fn end_transaction_at(
 892        &mut self,
 893        now: Instant,
 894        cx: &mut ModelContext<Self>,
 895    ) -> Option<TransactionId> {
 896        if let Some(buffer) = self.as_singleton() {
 897            return buffer.update(cx, |buffer, cx| buffer.end_transaction_at(now, cx));
 898        }
 899
 900        let mut buffer_transactions = HashMap::default();
 901        for BufferState { buffer, .. } in self.buffers.borrow().values() {
 902            if let Some(transaction_id) =
 903                buffer.update(cx, |buffer, cx| buffer.end_transaction_at(now, cx))
 904            {
 905                buffer_transactions.insert(buffer.read(cx).remote_id(), transaction_id);
 906            }
 907        }
 908
 909        if self.history.end_transaction(now, buffer_transactions) {
 910            let transaction_id = self.history.group().unwrap();
 911            Some(transaction_id)
 912        } else {
 913            None
 914        }
 915    }
 916
 917    pub fn edited_ranges_for_transaction<D>(
 918        &self,
 919        transaction_id: TransactionId,
 920        cx: &AppContext,
 921    ) -> Vec<Range<D>>
 922    where
 923        D: TextDimension + Ord + Sub<D, Output = D>,
 924    {
 925        if let Some(buffer) = self.as_singleton() {
 926            return buffer
 927                .read(cx)
 928                .edited_ranges_for_transaction_id(transaction_id)
 929                .collect::<Vec<_>>();
 930        }
 931
 932        let Some(transaction) = self.history.transaction(transaction_id) else {
 933            return Vec::new();
 934        };
 935
 936        let mut ranges = Vec::new();
 937        let snapshot = self.read(cx);
 938        let buffers = self.buffers.borrow();
 939        let mut cursor = snapshot.excerpts.cursor::<ExcerptSummary>(&());
 940
 941        for (buffer_id, buffer_transaction) in &transaction.buffer_transactions {
 942            let Some(buffer_state) = buffers.get(buffer_id) else {
 943                continue;
 944            };
 945
 946            let buffer = buffer_state.buffer.read(cx);
 947            for range in buffer.edited_ranges_for_transaction_id::<D>(*buffer_transaction) {
 948                for excerpt_id in &buffer_state.excerpts {
 949                    cursor.seek(excerpt_id, Bias::Left, &());
 950                    if let Some(excerpt) = cursor.item() {
 951                        if excerpt.locator == *excerpt_id {
 952                            let excerpt_buffer_start =
 953                                excerpt.range.context.start.summary::<D>(buffer);
 954                            let excerpt_buffer_end = excerpt.range.context.end.summary::<D>(buffer);
 955                            let excerpt_range = excerpt_buffer_start.clone()..excerpt_buffer_end;
 956                            if excerpt_range.contains(&range.start)
 957                                && excerpt_range.contains(&range.end)
 958                            {
 959                                let excerpt_start = D::from_text_summary(&cursor.start().text);
 960
 961                                let mut start = excerpt_start.clone();
 962                                start.add_assign(&(range.start - excerpt_buffer_start.clone()));
 963                                let mut end = excerpt_start;
 964                                end.add_assign(&(range.end - excerpt_buffer_start));
 965
 966                                ranges.push(start..end);
 967                                break;
 968                            }
 969                        }
 970                    }
 971                }
 972            }
 973        }
 974
 975        ranges.sort_by_key(|range| range.start.clone());
 976        ranges
 977    }
 978
 979    pub fn merge_transactions(
 980        &mut self,
 981        transaction: TransactionId,
 982        destination: TransactionId,
 983        cx: &mut ModelContext<Self>,
 984    ) {
 985        if let Some(buffer) = self.as_singleton() {
 986            buffer.update(cx, |buffer, _| {
 987                buffer.merge_transactions(transaction, destination)
 988            });
 989        } else if let Some(transaction) = self.history.forget(transaction) {
 990            if let Some(destination) = self.history.transaction_mut(destination) {
 991                for (buffer_id, buffer_transaction_id) in transaction.buffer_transactions {
 992                    if let Some(destination_buffer_transaction_id) =
 993                        destination.buffer_transactions.get(&buffer_id)
 994                    {
 995                        if let Some(state) = self.buffers.borrow().get(&buffer_id) {
 996                            state.buffer.update(cx, |buffer, _| {
 997                                buffer.merge_transactions(
 998                                    buffer_transaction_id,
 999                                    *destination_buffer_transaction_id,
1000                                )
1001                            });
1002                        }
1003                    } else {
1004                        destination
1005                            .buffer_transactions
1006                            .insert(buffer_id, buffer_transaction_id);
1007                    }
1008                }
1009            }
1010        }
1011    }
1012
1013    pub fn finalize_last_transaction(&mut self, cx: &mut ModelContext<Self>) {
1014        self.history.finalize_last_transaction();
1015        for BufferState { buffer, .. } in self.buffers.borrow().values() {
1016            buffer.update(cx, |buffer, _| {
1017                buffer.finalize_last_transaction();
1018            });
1019        }
1020    }
1021
1022    pub fn push_transaction<'a, T>(&mut self, buffer_transactions: T, cx: &ModelContext<Self>)
1023    where
1024        T: IntoIterator<Item = (&'a Model<Buffer>, &'a language::Transaction)>,
1025    {
1026        self.history
1027            .push_transaction(buffer_transactions, Instant::now(), cx);
1028        self.history.finalize_last_transaction();
1029    }
1030
1031    pub fn group_until_transaction(
1032        &mut self,
1033        transaction_id: TransactionId,
1034        cx: &mut ModelContext<Self>,
1035    ) {
1036        if let Some(buffer) = self.as_singleton() {
1037            buffer.update(cx, |buffer, _| {
1038                buffer.group_until_transaction(transaction_id)
1039            });
1040        } else {
1041            self.history.group_until(transaction_id);
1042        }
1043    }
1044
1045    pub fn set_active_selections(
1046        &self,
1047        selections: &[Selection<Anchor>],
1048        line_mode: bool,
1049        cursor_shape: CursorShape,
1050        cx: &mut ModelContext<Self>,
1051    ) {
1052        let mut selections_by_buffer: HashMap<BufferId, Vec<Selection<text::Anchor>>> =
1053            Default::default();
1054        let snapshot = self.read(cx);
1055        let mut cursor = snapshot.excerpts.cursor::<Option<&Locator>>(&());
1056        for selection in selections {
1057            let start_locator = snapshot.excerpt_locator_for_id(selection.start.excerpt_id);
1058            let end_locator = snapshot.excerpt_locator_for_id(selection.end.excerpt_id);
1059
1060            cursor.seek(&Some(start_locator), Bias::Left, &());
1061            while let Some(excerpt) = cursor.item() {
1062                if excerpt.locator > *end_locator {
1063                    break;
1064                }
1065
1066                let mut start = excerpt.range.context.start;
1067                let mut end = excerpt.range.context.end;
1068                if excerpt.id == selection.start.excerpt_id {
1069                    start = selection.start.text_anchor;
1070                }
1071                if excerpt.id == selection.end.excerpt_id {
1072                    end = selection.end.text_anchor;
1073                }
1074                selections_by_buffer
1075                    .entry(excerpt.buffer_id)
1076                    .or_default()
1077                    .push(Selection {
1078                        id: selection.id,
1079                        start,
1080                        end,
1081                        reversed: selection.reversed,
1082                        goal: selection.goal,
1083                    });
1084
1085                cursor.next(&());
1086            }
1087        }
1088
1089        for (buffer_id, buffer_state) in self.buffers.borrow().iter() {
1090            if !selections_by_buffer.contains_key(buffer_id) {
1091                buffer_state
1092                    .buffer
1093                    .update(cx, |buffer, cx| buffer.remove_active_selections(cx));
1094            }
1095        }
1096
1097        for (buffer_id, mut selections) in selections_by_buffer {
1098            self.buffers.borrow()[&buffer_id]
1099                .buffer
1100                .update(cx, |buffer, cx| {
1101                    selections.sort_unstable_by(|a, b| a.start.cmp(&b.start, buffer));
1102                    let mut selections = selections.into_iter().peekable();
1103                    let merged_selections = Arc::from_iter(iter::from_fn(|| {
1104                        let mut selection = selections.next()?;
1105                        while let Some(next_selection) = selections.peek() {
1106                            if selection.end.cmp(&next_selection.start, buffer).is_ge() {
1107                                let next_selection = selections.next().unwrap();
1108                                if next_selection.end.cmp(&selection.end, buffer).is_ge() {
1109                                    selection.end = next_selection.end;
1110                                }
1111                            } else {
1112                                break;
1113                            }
1114                        }
1115                        Some(selection)
1116                    }));
1117                    buffer.set_active_selections(merged_selections, line_mode, cursor_shape, cx);
1118                });
1119        }
1120    }
1121
1122    pub fn remove_active_selections(&self, cx: &mut ModelContext<Self>) {
1123        for buffer in self.buffers.borrow().values() {
1124            buffer
1125                .buffer
1126                .update(cx, |buffer, cx| buffer.remove_active_selections(cx));
1127        }
1128    }
1129
1130    pub fn undo(&mut self, cx: &mut ModelContext<Self>) -> Option<TransactionId> {
1131        let mut transaction_id = None;
1132        if let Some(buffer) = self.as_singleton() {
1133            transaction_id = buffer.update(cx, |buffer, cx| buffer.undo(cx));
1134        } else {
1135            while let Some(transaction) = self.history.pop_undo() {
1136                let mut undone = false;
1137                for (buffer_id, buffer_transaction_id) in &mut transaction.buffer_transactions {
1138                    if let Some(BufferState { buffer, .. }) = self.buffers.borrow().get(buffer_id) {
1139                        undone |= buffer.update(cx, |buffer, cx| {
1140                            let undo_to = *buffer_transaction_id;
1141                            if let Some(entry) = buffer.peek_undo_stack() {
1142                                *buffer_transaction_id = entry.transaction_id();
1143                            }
1144                            buffer.undo_to_transaction(undo_to, cx)
1145                        });
1146                    }
1147                }
1148
1149                if undone {
1150                    transaction_id = Some(transaction.id);
1151                    break;
1152                }
1153            }
1154        }
1155
1156        if let Some(transaction_id) = transaction_id {
1157            cx.emit(Event::TransactionUndone { transaction_id });
1158        }
1159
1160        transaction_id
1161    }
1162
1163    pub fn redo(&mut self, cx: &mut ModelContext<Self>) -> Option<TransactionId> {
1164        if let Some(buffer) = self.as_singleton() {
1165            return buffer.update(cx, |buffer, cx| buffer.redo(cx));
1166        }
1167
1168        while let Some(transaction) = self.history.pop_redo() {
1169            let mut redone = false;
1170            for (buffer_id, buffer_transaction_id) in &mut transaction.buffer_transactions {
1171                if let Some(BufferState { buffer, .. }) = self.buffers.borrow().get(buffer_id) {
1172                    redone |= buffer.update(cx, |buffer, cx| {
1173                        let redo_to = *buffer_transaction_id;
1174                        if let Some(entry) = buffer.peek_redo_stack() {
1175                            *buffer_transaction_id = entry.transaction_id();
1176                        }
1177                        buffer.redo_to_transaction(redo_to, cx)
1178                    });
1179                }
1180            }
1181
1182            if redone {
1183                return Some(transaction.id);
1184            }
1185        }
1186
1187        None
1188    }
1189
1190    pub fn undo_transaction(&mut self, transaction_id: TransactionId, cx: &mut ModelContext<Self>) {
1191        if let Some(buffer) = self.as_singleton() {
1192            buffer.update(cx, |buffer, cx| buffer.undo_transaction(transaction_id, cx));
1193        } else if let Some(transaction) = self.history.remove_from_undo(transaction_id) {
1194            for (buffer_id, transaction_id) in &transaction.buffer_transactions {
1195                if let Some(BufferState { buffer, .. }) = self.buffers.borrow().get(buffer_id) {
1196                    buffer.update(cx, |buffer, cx| {
1197                        buffer.undo_transaction(*transaction_id, cx)
1198                    });
1199                }
1200            }
1201        }
1202    }
1203
1204    pub fn forget_transaction(
1205        &mut self,
1206        transaction_id: TransactionId,
1207        cx: &mut ModelContext<Self>,
1208    ) {
1209        if let Some(buffer) = self.as_singleton() {
1210            buffer.update(cx, |buffer, _| {
1211                buffer.forget_transaction(transaction_id);
1212            });
1213        } else if let Some(transaction) = self.history.forget(transaction_id) {
1214            for (buffer_id, buffer_transaction_id) in transaction.buffer_transactions {
1215                if let Some(state) = self.buffers.borrow_mut().get_mut(&buffer_id) {
1216                    state.buffer.update(cx, |buffer, _| {
1217                        buffer.forget_transaction(buffer_transaction_id);
1218                    });
1219                }
1220            }
1221        }
1222    }
1223
1224    pub fn push_excerpts<O>(
1225        &mut self,
1226        buffer: Model<Buffer>,
1227        ranges: impl IntoIterator<Item = ExcerptRange<O>>,
1228        cx: &mut ModelContext<Self>,
1229    ) -> Vec<ExcerptId>
1230    where
1231        O: text::ToOffset,
1232    {
1233        self.insert_excerpts_after(ExcerptId::max(), buffer, ranges, cx)
1234    }
1235
1236    pub fn push_excerpts_with_context_lines<O>(
1237        &mut self,
1238        buffer: Model<Buffer>,
1239        ranges: Vec<Range<O>>,
1240        context_line_count: u32,
1241        cx: &mut ModelContext<Self>,
1242    ) -> Vec<Range<Anchor>>
1243    where
1244        O: text::ToPoint + text::ToOffset,
1245    {
1246        let buffer_id = buffer.read(cx).remote_id();
1247        let buffer_snapshot = buffer.read(cx).snapshot();
1248        let (excerpt_ranges, range_counts) =
1249            build_excerpt_ranges(&buffer_snapshot, &ranges, context_line_count);
1250
1251        let excerpt_ids = self.push_excerpts(buffer, excerpt_ranges, cx);
1252
1253        let mut anchor_ranges = Vec::new();
1254        let mut ranges = ranges.into_iter();
1255        for (excerpt_id, range_count) in excerpt_ids.into_iter().zip(range_counts.into_iter()) {
1256            anchor_ranges.extend(ranges.by_ref().take(range_count).map(|range| {
1257                let start = Anchor {
1258                    buffer_id: Some(buffer_id),
1259                    excerpt_id,
1260                    text_anchor: buffer_snapshot.anchor_after(range.start),
1261                };
1262                let end = Anchor {
1263                    buffer_id: Some(buffer_id),
1264                    excerpt_id,
1265                    text_anchor: buffer_snapshot.anchor_after(range.end),
1266                };
1267                start..end
1268            }))
1269        }
1270        anchor_ranges
1271    }
1272
1273    pub fn push_multiple_excerpts_with_context_lines(
1274        &self,
1275        buffers_with_ranges: Vec<(Model<Buffer>, Vec<Range<text::Anchor>>)>,
1276        context_line_count: u32,
1277        cx: &mut ModelContext<Self>,
1278    ) -> Task<Vec<Range<Anchor>>> {
1279        use futures::StreamExt;
1280
1281        let (excerpt_ranges_tx, mut excerpt_ranges_rx) = mpsc::channel(256);
1282
1283        let mut buffer_ids = Vec::with_capacity(buffers_with_ranges.len());
1284
1285        for (buffer, ranges) in buffers_with_ranges {
1286            let (buffer_id, buffer_snapshot) =
1287                buffer.update(cx, |buffer, _| (buffer.remote_id(), buffer.snapshot()));
1288
1289            buffer_ids.push(buffer_id);
1290
1291            cx.background_executor()
1292                .spawn({
1293                    let mut excerpt_ranges_tx = excerpt_ranges_tx.clone();
1294
1295                    async move {
1296                        let (excerpt_ranges, counts) =
1297                            build_excerpt_ranges(&buffer_snapshot, &ranges, context_line_count);
1298                        excerpt_ranges_tx
1299                            .send((buffer_id, buffer.clone(), ranges, excerpt_ranges, counts))
1300                            .await
1301                            .ok();
1302                    }
1303                })
1304                .detach()
1305        }
1306
1307        cx.spawn(move |this, mut cx| async move {
1308            let mut results_by_buffer_id = HashMap::default();
1309            while let Some((buffer_id, buffer, ranges, excerpt_ranges, range_counts)) =
1310                excerpt_ranges_rx.next().await
1311            {
1312                results_by_buffer_id
1313                    .insert(buffer_id, (buffer, ranges, excerpt_ranges, range_counts));
1314            }
1315
1316            let mut multi_buffer_ranges = Vec::default();
1317            'outer: for buffer_id in buffer_ids {
1318                let Some((buffer, ranges, excerpt_ranges, range_counts)) =
1319                    results_by_buffer_id.remove(&buffer_id)
1320                else {
1321                    continue;
1322                };
1323
1324                let mut ranges = ranges.into_iter();
1325                let mut range_counts = range_counts.into_iter();
1326                for excerpt_ranges in excerpt_ranges.chunks(100) {
1327                    let excerpt_ids = match this.update(&mut cx, |this, cx| {
1328                        this.push_excerpts(buffer.clone(), excerpt_ranges.iter().cloned(), cx)
1329                    }) {
1330                        Ok(excerpt_ids) => excerpt_ids,
1331                        Err(_) => continue 'outer,
1332                    };
1333
1334                    for (excerpt_id, range_count) in
1335                        excerpt_ids.into_iter().zip(range_counts.by_ref())
1336                    {
1337                        for range in ranges.by_ref().take(range_count) {
1338                            let start = Anchor {
1339                                buffer_id: Some(buffer_id),
1340                                excerpt_id,
1341                                text_anchor: range.start,
1342                            };
1343                            let end = Anchor {
1344                                buffer_id: Some(buffer_id),
1345                                excerpt_id,
1346                                text_anchor: range.end,
1347                            };
1348                            multi_buffer_ranges.push(start..end);
1349                        }
1350                    }
1351                }
1352            }
1353
1354            multi_buffer_ranges
1355        })
1356    }
1357
1358    pub fn insert_excerpts_after<O>(
1359        &mut self,
1360        prev_excerpt_id: ExcerptId,
1361        buffer: Model<Buffer>,
1362        ranges: impl IntoIterator<Item = ExcerptRange<O>>,
1363        cx: &mut ModelContext<Self>,
1364    ) -> Vec<ExcerptId>
1365    where
1366        O: text::ToOffset,
1367    {
1368        let mut ids = Vec::new();
1369        let mut next_excerpt_id =
1370            if let Some(last_entry) = self.snapshot.borrow().excerpt_ids.last() {
1371                last_entry.id.0 + 1
1372            } else {
1373                1
1374            };
1375        self.insert_excerpts_with_ids_after(
1376            prev_excerpt_id,
1377            buffer,
1378            ranges.into_iter().map(|range| {
1379                let id = ExcerptId(post_inc(&mut next_excerpt_id));
1380                ids.push(id);
1381                (id, range)
1382            }),
1383            cx,
1384        );
1385        ids
1386    }
1387
1388    pub fn insert_excerpts_with_ids_after<O>(
1389        &mut self,
1390        prev_excerpt_id: ExcerptId,
1391        buffer: Model<Buffer>,
1392        ranges: impl IntoIterator<Item = (ExcerptId, ExcerptRange<O>)>,
1393        cx: &mut ModelContext<Self>,
1394    ) where
1395        O: text::ToOffset,
1396    {
1397        assert_eq!(self.history.transaction_depth, 0);
1398        let mut ranges = ranges.into_iter().peekable();
1399        if ranges.peek().is_none() {
1400            return Default::default();
1401        }
1402
1403        self.sync(cx);
1404
1405        let buffer_id = buffer.read(cx).remote_id();
1406        let buffer_snapshot = buffer.read(cx).snapshot();
1407
1408        let mut buffers = self.buffers.borrow_mut();
1409        let buffer_state = buffers.entry(buffer_id).or_insert_with(|| BufferState {
1410            last_version: buffer_snapshot.version().clone(),
1411            last_non_text_state_update_count: buffer_snapshot.non_text_state_update_count(),
1412            excerpts: Default::default(),
1413            _subscriptions: [
1414                cx.observe(&buffer, |_, _, cx| cx.notify()),
1415                cx.subscribe(&buffer, Self::on_buffer_event),
1416            ],
1417            buffer: buffer.clone(),
1418        });
1419
1420        let mut snapshot = self.snapshot.borrow_mut();
1421
1422        let mut prev_locator = snapshot.excerpt_locator_for_id(prev_excerpt_id).clone();
1423        let mut new_excerpt_ids = mem::take(&mut snapshot.excerpt_ids);
1424        let mut cursor = snapshot.excerpts.cursor::<Option<&Locator>>(&());
1425        let mut new_excerpts = cursor.slice(&prev_locator, Bias::Right, &());
1426        prev_locator = cursor.start().unwrap_or(Locator::min_ref()).clone();
1427
1428        let edit_start = new_excerpts.summary().text.len;
1429        new_excerpts.update_last(
1430            |excerpt| {
1431                excerpt.has_trailing_newline = true;
1432            },
1433            &(),
1434        );
1435
1436        let next_locator = if let Some(excerpt) = cursor.item() {
1437            excerpt.locator.clone()
1438        } else {
1439            Locator::max()
1440        };
1441
1442        let mut excerpts = Vec::new();
1443        while let Some((id, range)) = ranges.next() {
1444            let locator = Locator::between(&prev_locator, &next_locator);
1445            if let Err(ix) = buffer_state.excerpts.binary_search(&locator) {
1446                buffer_state.excerpts.insert(ix, locator.clone());
1447            }
1448            let range = ExcerptRange {
1449                context: buffer_snapshot.anchor_before(&range.context.start)
1450                    ..buffer_snapshot.anchor_after(&range.context.end),
1451                primary: range.primary.map(|primary| {
1452                    buffer_snapshot.anchor_before(&primary.start)
1453                        ..buffer_snapshot.anchor_after(&primary.end)
1454                }),
1455            };
1456            excerpts.push((id, range.clone()));
1457            let excerpt = Excerpt::new(
1458                id,
1459                locator.clone(),
1460                buffer_id,
1461                buffer_snapshot.clone(),
1462                range,
1463                ranges.peek().is_some() || cursor.item().is_some(),
1464            );
1465            new_excerpts.push(excerpt, &());
1466            prev_locator = locator.clone();
1467
1468            if let Some(last_mapping_entry) = new_excerpt_ids.last() {
1469                assert!(id > last_mapping_entry.id, "excerpt ids must be increasing");
1470            }
1471            new_excerpt_ids.push(ExcerptIdMapping { id, locator }, &());
1472        }
1473
1474        let edit_end = new_excerpts.summary().text.len;
1475
1476        let suffix = cursor.suffix(&());
1477        let changed_trailing_excerpt = suffix.is_empty();
1478        new_excerpts.append(suffix, &());
1479        drop(cursor);
1480        snapshot.excerpts = new_excerpts;
1481        snapshot.excerpt_ids = new_excerpt_ids;
1482        if changed_trailing_excerpt {
1483            snapshot.trailing_excerpt_update_count += 1;
1484        }
1485
1486        self.subscriptions.publish_mut([Edit {
1487            old: edit_start..edit_start,
1488            new: edit_start..edit_end,
1489        }]);
1490        cx.emit(Event::Edited {
1491            singleton_buffer_edited: false,
1492            edited_buffer: None,
1493        });
1494        cx.emit(Event::ExcerptsAdded {
1495            buffer,
1496            predecessor: prev_excerpt_id,
1497            excerpts,
1498        });
1499        cx.notify();
1500    }
1501
1502    pub fn clear(&mut self, cx: &mut ModelContext<Self>) {
1503        self.sync(cx);
1504        let ids = self.excerpt_ids();
1505        self.buffers.borrow_mut().clear();
1506        let mut snapshot = self.snapshot.borrow_mut();
1507        let prev_len = snapshot.len();
1508        snapshot.excerpts = Default::default();
1509        snapshot.trailing_excerpt_update_count += 1;
1510        snapshot.is_dirty = false;
1511        snapshot.has_deleted_file = false;
1512        snapshot.has_conflict = false;
1513
1514        self.subscriptions.publish_mut([Edit {
1515            old: 0..prev_len,
1516            new: 0..0,
1517        }]);
1518        cx.emit(Event::Edited {
1519            singleton_buffer_edited: false,
1520            edited_buffer: None,
1521        });
1522        cx.emit(Event::ExcerptsRemoved { ids });
1523        cx.notify();
1524    }
1525
1526    pub fn excerpts_for_buffer(
1527        &self,
1528        buffer: &Model<Buffer>,
1529        cx: &AppContext,
1530    ) -> Vec<(ExcerptId, ExcerptRange<text::Anchor>)> {
1531        let mut excerpts = Vec::new();
1532        let snapshot = self.read(cx);
1533        let buffers = self.buffers.borrow();
1534        let mut cursor = snapshot.excerpts.cursor::<Option<&Locator>>(&());
1535        for locator in buffers
1536            .get(&buffer.read(cx).remote_id())
1537            .map(|state| &state.excerpts)
1538            .into_iter()
1539            .flatten()
1540        {
1541            cursor.seek_forward(&Some(locator), Bias::Left, &());
1542            if let Some(excerpt) = cursor.item() {
1543                if excerpt.locator == *locator {
1544                    excerpts.push((excerpt.id, excerpt.range.clone()));
1545                }
1546            }
1547        }
1548
1549        excerpts
1550    }
1551
1552    pub fn excerpt_ranges_for_buffer(
1553        &self,
1554        buffer_id: BufferId,
1555        cx: &AppContext,
1556    ) -> Vec<Range<Point>> {
1557        let snapshot = self.read(cx);
1558        let buffers = self.buffers.borrow();
1559        let mut cursor = snapshot.excerpts.cursor::<(Option<&Locator>, Point)>(&());
1560        buffers
1561            .get(&buffer_id)
1562            .into_iter()
1563            .flat_map(|state| &state.excerpts)
1564            .filter_map(move |locator| {
1565                cursor.seek_forward(&Some(locator), Bias::Left, &());
1566                cursor.item().and_then(|excerpt| {
1567                    if excerpt.locator == *locator {
1568                        let excerpt_start = cursor.start().1;
1569                        let excerpt_end = excerpt_start + excerpt.text_summary.lines;
1570                        Some(excerpt_start..excerpt_end)
1571                    } else {
1572                        None
1573                    }
1574                })
1575            })
1576            .collect()
1577    }
1578
1579    pub fn excerpt_buffer_ids(&self) -> Vec<BufferId> {
1580        self.snapshot
1581            .borrow()
1582            .excerpts
1583            .iter()
1584            .map(|entry| entry.buffer_id)
1585            .collect()
1586    }
1587
1588    pub fn excerpt_ids(&self) -> Vec<ExcerptId> {
1589        self.snapshot
1590            .borrow()
1591            .excerpts
1592            .iter()
1593            .map(|entry| entry.id)
1594            .collect()
1595    }
1596
1597    pub fn excerpt_containing(
1598        &self,
1599        position: impl ToOffset,
1600        cx: &AppContext,
1601    ) -> Option<(ExcerptId, Model<Buffer>, Range<text::Anchor>)> {
1602        let snapshot = self.read(cx);
1603        let position = position.to_offset(&snapshot);
1604
1605        let mut cursor = snapshot.excerpts.cursor::<usize>(&());
1606        cursor.seek(&position, Bias::Right, &());
1607        cursor
1608            .item()
1609            .or_else(|| snapshot.excerpts.last())
1610            .map(|excerpt| {
1611                (
1612                    excerpt.id,
1613                    self.buffers
1614                        .borrow()
1615                        .get(&excerpt.buffer_id)
1616                        .unwrap()
1617                        .buffer
1618                        .clone(),
1619                    excerpt.range.context.clone(),
1620                )
1621            })
1622    }
1623
1624    // If point is at the end of the buffer, the last excerpt is returned
1625    pub fn point_to_buffer_offset<T: ToOffset>(
1626        &self,
1627        point: T,
1628        cx: &AppContext,
1629    ) -> Option<(Model<Buffer>, usize, ExcerptId)> {
1630        let snapshot = self.read(cx);
1631        let offset = point.to_offset(&snapshot);
1632        let mut cursor = snapshot.excerpts.cursor::<usize>(&());
1633        cursor.seek(&offset, Bias::Right, &());
1634        if cursor.item().is_none() {
1635            cursor.prev(&());
1636        }
1637
1638        cursor.item().map(|excerpt| {
1639            let excerpt_start = excerpt.range.context.start.to_offset(&excerpt.buffer);
1640            let buffer_point = excerpt_start + offset - *cursor.start();
1641            let buffer = self.buffers.borrow()[&excerpt.buffer_id].buffer.clone();
1642
1643            (buffer, buffer_point, excerpt.id)
1644        })
1645    }
1646
1647    // If point is at the end of the buffer, the last excerpt is returned
1648    pub fn point_to_buffer_point<T: ToPoint>(
1649        &self,
1650        point: T,
1651        cx: &AppContext,
1652    ) -> Option<(Model<Buffer>, Point, ExcerptId)> {
1653        let snapshot = self.read(cx);
1654        let point = point.to_point(&snapshot);
1655        let mut cursor = snapshot.excerpts.cursor::<Point>(&());
1656        cursor.seek(&point, Bias::Right, &());
1657        if cursor.item().is_none() {
1658            cursor.prev(&());
1659        }
1660
1661        cursor.item().map(|excerpt| {
1662            let excerpt_start = excerpt.range.context.start.to_point(&excerpt.buffer);
1663            let buffer_point = excerpt_start + point - *cursor.start();
1664            let buffer = self.buffers.borrow()[&excerpt.buffer_id].buffer.clone();
1665
1666            (buffer, buffer_point, excerpt.id)
1667        })
1668    }
1669
1670    pub fn remove_excerpts(
1671        &mut self,
1672        excerpt_ids: impl IntoIterator<Item = ExcerptId>,
1673        cx: &mut ModelContext<Self>,
1674    ) {
1675        self.sync(cx);
1676        let ids = excerpt_ids.into_iter().collect::<Vec<_>>();
1677        if ids.is_empty() {
1678            return;
1679        }
1680
1681        let mut buffers = self.buffers.borrow_mut();
1682        let mut snapshot = self.snapshot.borrow_mut();
1683        let mut new_excerpts = SumTree::default();
1684        let mut cursor = snapshot.excerpts.cursor::<(Option<&Locator>, usize)>(&());
1685        let mut edits = Vec::new();
1686        let mut excerpt_ids = ids.iter().copied().peekable();
1687
1688        while let Some(excerpt_id) = excerpt_ids.next() {
1689            // Seek to the next excerpt to remove, preserving any preceding excerpts.
1690            let locator = snapshot.excerpt_locator_for_id(excerpt_id);
1691            new_excerpts.append(cursor.slice(&Some(locator), Bias::Left, &()), &());
1692
1693            if let Some(mut excerpt) = cursor.item() {
1694                if excerpt.id != excerpt_id {
1695                    continue;
1696                }
1697                let mut old_start = cursor.start().1;
1698
1699                // Skip over the removed excerpt.
1700                'remove_excerpts: loop {
1701                    if let Some(buffer_state) = buffers.get_mut(&excerpt.buffer_id) {
1702                        buffer_state.excerpts.retain(|l| l != &excerpt.locator);
1703                        if buffer_state.excerpts.is_empty() {
1704                            buffers.remove(&excerpt.buffer_id);
1705                        }
1706                    }
1707                    cursor.next(&());
1708
1709                    // Skip over any subsequent excerpts that are also removed.
1710                    if let Some(&next_excerpt_id) = excerpt_ids.peek() {
1711                        let next_locator = snapshot.excerpt_locator_for_id(next_excerpt_id);
1712                        if let Some(next_excerpt) = cursor.item() {
1713                            if next_excerpt.locator == *next_locator {
1714                                excerpt_ids.next();
1715                                excerpt = next_excerpt;
1716                                continue 'remove_excerpts;
1717                            }
1718                        }
1719                    }
1720
1721                    break;
1722                }
1723
1724                // When removing the last excerpt, remove the trailing newline from
1725                // the previous excerpt.
1726                if cursor.item().is_none() && old_start > 0 {
1727                    old_start -= 1;
1728                    new_excerpts.update_last(|e| e.has_trailing_newline = false, &());
1729                }
1730
1731                // Push an edit for the removal of this run of excerpts.
1732                let old_end = cursor.start().1;
1733                let new_start = new_excerpts.summary().text.len;
1734                edits.push(Edit {
1735                    old: old_start..old_end,
1736                    new: new_start..new_start,
1737                });
1738            }
1739        }
1740        let suffix = cursor.suffix(&());
1741        let changed_trailing_excerpt = suffix.is_empty();
1742        new_excerpts.append(suffix, &());
1743        drop(cursor);
1744        snapshot.excerpts = new_excerpts;
1745
1746        if changed_trailing_excerpt {
1747            snapshot.trailing_excerpt_update_count += 1;
1748        }
1749
1750        self.subscriptions.publish_mut(edits);
1751        cx.emit(Event::Edited {
1752            singleton_buffer_edited: false,
1753            edited_buffer: None,
1754        });
1755        cx.emit(Event::ExcerptsRemoved { ids });
1756        cx.notify();
1757    }
1758
1759    pub fn wait_for_anchors<'a>(
1760        &self,
1761        anchors: impl 'a + Iterator<Item = Anchor>,
1762        cx: &mut ModelContext<Self>,
1763    ) -> impl 'static + Future<Output = Result<()>> {
1764        let borrow = self.buffers.borrow();
1765        let mut error = None;
1766        let mut futures = Vec::new();
1767        for anchor in anchors {
1768            if let Some(buffer_id) = anchor.buffer_id {
1769                if let Some(buffer) = borrow.get(&buffer_id) {
1770                    buffer.buffer.update(cx, |buffer, _| {
1771                        futures.push(buffer.wait_for_anchors([anchor.text_anchor]))
1772                    });
1773                } else {
1774                    error = Some(anyhow!(
1775                        "buffer {buffer_id} is not part of this multi-buffer"
1776                    ));
1777                    break;
1778                }
1779            }
1780        }
1781        async move {
1782            if let Some(error) = error {
1783                Err(error)?;
1784            }
1785            for future in futures {
1786                future.await?;
1787            }
1788            Ok(())
1789        }
1790    }
1791
1792    pub fn text_anchor_for_position<T: ToOffset>(
1793        &self,
1794        position: T,
1795        cx: &AppContext,
1796    ) -> Option<(Model<Buffer>, language::Anchor)> {
1797        let snapshot = self.read(cx);
1798        let anchor = snapshot.anchor_before(position);
1799        let buffer = self
1800            .buffers
1801            .borrow()
1802            .get(&anchor.buffer_id?)?
1803            .buffer
1804            .clone();
1805        Some((buffer, anchor.text_anchor))
1806    }
1807
1808    fn on_buffer_event(
1809        &mut self,
1810        buffer: Model<Buffer>,
1811        event: &language::BufferEvent,
1812        cx: &mut ModelContext<Self>,
1813    ) {
1814        cx.emit(match event {
1815            language::BufferEvent::Edited => Event::Edited {
1816                singleton_buffer_edited: true,
1817                edited_buffer: Some(buffer.clone()),
1818            },
1819            language::BufferEvent::DirtyChanged => Event::DirtyChanged,
1820            language::BufferEvent::Saved => Event::Saved,
1821            language::BufferEvent::FileHandleChanged => Event::FileHandleChanged,
1822            language::BufferEvent::Reloaded => Event::Reloaded,
1823            language::BufferEvent::ReloadNeeded => Event::ReloadNeeded,
1824            language::BufferEvent::LanguageChanged => {
1825                Event::LanguageChanged(buffer.read(cx).remote_id())
1826            }
1827            language::BufferEvent::Reparsed => Event::Reparsed(buffer.read(cx).remote_id()),
1828            language::BufferEvent::DiagnosticsUpdated => Event::DiagnosticsUpdated,
1829            language::BufferEvent::Closed => Event::Closed,
1830            language::BufferEvent::Discarded => Event::Discarded,
1831            language::BufferEvent::CapabilityChanged => {
1832                self.capability = buffer.read(cx).capability();
1833                Event::CapabilityChanged
1834            }
1835            //
1836            language::BufferEvent::Operation { .. } => return,
1837        });
1838    }
1839
1840    pub fn all_buffers(&self) -> HashSet<Model<Buffer>> {
1841        self.buffers
1842            .borrow()
1843            .values()
1844            .map(|state| state.buffer.clone())
1845            .collect()
1846    }
1847
1848    pub fn buffer(&self, buffer_id: BufferId) -> Option<Model<Buffer>> {
1849        self.buffers
1850            .borrow()
1851            .get(&buffer_id)
1852            .map(|state| state.buffer.clone())
1853    }
1854
1855    pub fn language_at<T: ToOffset>(&self, point: T, cx: &AppContext) -> Option<Arc<Language>> {
1856        self.point_to_buffer_offset(point, cx)
1857            .and_then(|(buffer, offset, _)| buffer.read(cx).language_at(offset))
1858    }
1859
1860    pub fn settings_at<'a, T: ToOffset>(
1861        &self,
1862        point: T,
1863        cx: &'a AppContext,
1864    ) -> Cow<'a, LanguageSettings> {
1865        let mut language = None;
1866        let mut file = None;
1867        if let Some((buffer, offset, _)) = self.point_to_buffer_offset(point, cx) {
1868            let buffer = buffer.read(cx);
1869            language = buffer.language_at(offset);
1870            file = buffer.file();
1871        }
1872        language_settings(language.map(|l| l.name()), file, cx)
1873    }
1874
1875    pub fn for_each_buffer(&self, mut f: impl FnMut(&Model<Buffer>)) {
1876        self.buffers
1877            .borrow()
1878            .values()
1879            .for_each(|state| f(&state.buffer))
1880    }
1881
1882    pub fn title<'a>(&'a self, cx: &'a AppContext) -> Cow<'a, str> {
1883        if let Some(title) = self.title.as_ref() {
1884            return title.into();
1885        }
1886
1887        if let Some(buffer) = self.as_singleton() {
1888            if let Some(file) = buffer.read(cx).file() {
1889                return file.file_name(cx).to_string_lossy();
1890            }
1891        }
1892
1893        "untitled".into()
1894    }
1895
1896    pub fn set_title(&mut self, title: String, cx: &mut ModelContext<Self>) {
1897        self.title = Some(title);
1898        cx.notify();
1899    }
1900
1901    /// Preserve preview tabs containing this multibuffer until additional edits occur.
1902    pub fn refresh_preview(&self, cx: &mut ModelContext<Self>) {
1903        for buffer_state in self.buffers.borrow().values() {
1904            buffer_state
1905                .buffer
1906                .update(cx, |buffer, _cx| buffer.refresh_preview());
1907        }
1908    }
1909
1910    /// Whether we should preserve the preview status of a tab containing this multi-buffer.
1911    pub fn preserve_preview(&self, cx: &AppContext) -> bool {
1912        self.buffers
1913            .borrow()
1914            .values()
1915            .all(|state| state.buffer.read(cx).preserve_preview())
1916    }
1917
1918    #[cfg(any(test, feature = "test-support"))]
1919    pub fn is_parsing(&self, cx: &AppContext) -> bool {
1920        self.as_singleton().unwrap().read(cx).is_parsing()
1921    }
1922
1923    pub fn resize_excerpt(
1924        &mut self,
1925        id: ExcerptId,
1926        range: Range<text::Anchor>,
1927        cx: &mut ModelContext<Self>,
1928    ) {
1929        self.sync(cx);
1930
1931        let snapshot = self.snapshot(cx);
1932        let locator = snapshot.excerpt_locator_for_id(id);
1933        let mut new_excerpts = SumTree::default();
1934        let mut cursor = snapshot.excerpts.cursor::<(Option<&Locator>, usize)>(&());
1935        let mut edits = Vec::<Edit<usize>>::new();
1936
1937        let prefix = cursor.slice(&Some(locator), Bias::Left, &());
1938        new_excerpts.append(prefix, &());
1939
1940        let mut excerpt = cursor.item().unwrap().clone();
1941        let old_text_len = excerpt.text_summary.len;
1942
1943        excerpt.range.context.start = range.start;
1944        excerpt.range.context.end = range.end;
1945        excerpt.max_buffer_row = range.end.to_point(&excerpt.buffer).row;
1946
1947        excerpt.text_summary = excerpt
1948            .buffer
1949            .text_summary_for_range(excerpt.range.context.clone());
1950
1951        let new_start_offset = new_excerpts.summary().text.len;
1952        let old_start_offset = cursor.start().1;
1953        let edit = Edit {
1954            old: old_start_offset..old_start_offset + old_text_len,
1955            new: new_start_offset..new_start_offset + excerpt.text_summary.len,
1956        };
1957
1958        if let Some(last_edit) = edits.last_mut() {
1959            if last_edit.old.end == edit.old.start {
1960                last_edit.old.end = edit.old.end;
1961                last_edit.new.end = edit.new.end;
1962            } else {
1963                edits.push(edit);
1964            }
1965        } else {
1966            edits.push(edit);
1967        }
1968
1969        new_excerpts.push(excerpt, &());
1970
1971        cursor.next(&());
1972
1973        new_excerpts.append(cursor.suffix(&()), &());
1974
1975        drop(cursor);
1976        self.snapshot.borrow_mut().excerpts = new_excerpts;
1977
1978        self.subscriptions.publish_mut(edits);
1979        cx.emit(Event::Edited {
1980            singleton_buffer_edited: false,
1981            edited_buffer: None,
1982        });
1983        cx.emit(Event::ExcerptsExpanded { ids: vec![id] });
1984        cx.notify();
1985    }
1986
1987    pub fn expand_excerpts(
1988        &mut self,
1989        ids: impl IntoIterator<Item = ExcerptId>,
1990        line_count: u32,
1991        direction: ExpandExcerptDirection,
1992        cx: &mut ModelContext<Self>,
1993    ) {
1994        if line_count == 0 {
1995            return;
1996        }
1997        self.sync(cx);
1998
1999        let ids = ids.into_iter().collect::<Vec<_>>();
2000        let snapshot = self.snapshot(cx);
2001        let locators = snapshot.excerpt_locators_for_ids(ids.iter().copied());
2002        let mut new_excerpts = SumTree::default();
2003        let mut cursor = snapshot.excerpts.cursor::<(Option<&Locator>, usize)>(&());
2004        let mut edits = Vec::<Edit<usize>>::new();
2005
2006        for locator in &locators {
2007            let prefix = cursor.slice(&Some(locator), Bias::Left, &());
2008            new_excerpts.append(prefix, &());
2009
2010            let mut excerpt = cursor.item().unwrap().clone();
2011            let old_text_len = excerpt.text_summary.len;
2012
2013            let up_line_count = if direction.should_expand_up() {
2014                line_count
2015            } else {
2016                0
2017            };
2018
2019            let start_row = excerpt
2020                .range
2021                .context
2022                .start
2023                .to_point(&excerpt.buffer)
2024                .row
2025                .saturating_sub(up_line_count);
2026            let start_point = Point::new(start_row, 0);
2027            excerpt.range.context.start = excerpt.buffer.anchor_before(start_point);
2028
2029            let down_line_count = if direction.should_expand_down() {
2030                line_count
2031            } else {
2032                0
2033            };
2034
2035            let mut end_point = excerpt.buffer.clip_point(
2036                excerpt.range.context.end.to_point(&excerpt.buffer)
2037                    + Point::new(down_line_count, 0),
2038                Bias::Left,
2039            );
2040            end_point.column = excerpt.buffer.line_len(end_point.row);
2041            excerpt.range.context.end = excerpt.buffer.anchor_after(end_point);
2042            excerpt.max_buffer_row = end_point.row;
2043
2044            excerpt.text_summary = excerpt
2045                .buffer
2046                .text_summary_for_range(excerpt.range.context.clone());
2047
2048            let new_start_offset = new_excerpts.summary().text.len;
2049            let old_start_offset = cursor.start().1;
2050            let edit = Edit {
2051                old: old_start_offset..old_start_offset + old_text_len,
2052                new: new_start_offset..new_start_offset + excerpt.text_summary.len,
2053            };
2054
2055            if let Some(last_edit) = edits.last_mut() {
2056                if last_edit.old.end == edit.old.start {
2057                    last_edit.old.end = edit.old.end;
2058                    last_edit.new.end = edit.new.end;
2059                } else {
2060                    edits.push(edit);
2061                }
2062            } else {
2063                edits.push(edit);
2064            }
2065
2066            new_excerpts.push(excerpt, &());
2067
2068            cursor.next(&());
2069        }
2070
2071        new_excerpts.append(cursor.suffix(&()), &());
2072
2073        drop(cursor);
2074        self.snapshot.borrow_mut().excerpts = new_excerpts;
2075
2076        self.subscriptions.publish_mut(edits);
2077        cx.emit(Event::Edited {
2078            singleton_buffer_edited: false,
2079            edited_buffer: None,
2080        });
2081        cx.emit(Event::ExcerptsExpanded { ids });
2082        cx.notify();
2083    }
2084
2085    fn sync(&self, cx: &AppContext) {
2086        let mut snapshot = self.snapshot.borrow_mut();
2087        let mut excerpts_to_edit = Vec::new();
2088        let mut non_text_state_updated = false;
2089        let mut is_dirty = false;
2090        let mut has_deleted_file = false;
2091        let mut has_conflict = false;
2092        let mut edited = false;
2093        let mut buffers = self.buffers.borrow_mut();
2094        for buffer_state in buffers.values_mut() {
2095            let buffer = buffer_state.buffer.read(cx);
2096            let version = buffer.version();
2097            let non_text_state_update_count = buffer.non_text_state_update_count();
2098
2099            let buffer_edited = version.changed_since(&buffer_state.last_version);
2100            let buffer_non_text_state_updated =
2101                non_text_state_update_count > buffer_state.last_non_text_state_update_count;
2102            if buffer_edited || buffer_non_text_state_updated {
2103                buffer_state.last_version = version;
2104                buffer_state.last_non_text_state_update_count = non_text_state_update_count;
2105                excerpts_to_edit.extend(
2106                    buffer_state
2107                        .excerpts
2108                        .iter()
2109                        .map(|locator| (locator, buffer_state.buffer.clone(), buffer_edited)),
2110                );
2111            }
2112
2113            edited |= buffer_edited;
2114            non_text_state_updated |= buffer_non_text_state_updated;
2115            is_dirty |= buffer.is_dirty();
2116            has_deleted_file |= buffer
2117                .file()
2118                .map_or(false, |file| file.disk_state() == DiskState::Deleted);
2119            has_conflict |= buffer.has_conflict();
2120        }
2121        if edited {
2122            snapshot.edit_count += 1;
2123        }
2124        if non_text_state_updated {
2125            snapshot.non_text_state_update_count += 1;
2126        }
2127        snapshot.is_dirty = is_dirty;
2128        snapshot.has_deleted_file = has_deleted_file;
2129        snapshot.has_conflict = has_conflict;
2130
2131        excerpts_to_edit.sort_unstable_by_key(|(locator, _, _)| *locator);
2132
2133        let mut edits = Vec::new();
2134        let mut new_excerpts = SumTree::default();
2135        let mut cursor = snapshot.excerpts.cursor::<(Option<&Locator>, usize)>(&());
2136
2137        for (locator, buffer, buffer_edited) in excerpts_to_edit {
2138            new_excerpts.append(cursor.slice(&Some(locator), Bias::Left, &()), &());
2139            let old_excerpt = cursor.item().unwrap();
2140            let buffer = buffer.read(cx);
2141            let buffer_id = buffer.remote_id();
2142
2143            let mut new_excerpt;
2144            if buffer_edited {
2145                edits.extend(
2146                    buffer
2147                        .edits_since_in_range::<usize>(
2148                            old_excerpt.buffer.version(),
2149                            old_excerpt.range.context.clone(),
2150                        )
2151                        .map(|mut edit| {
2152                            let excerpt_old_start = cursor.start().1;
2153                            let excerpt_new_start = new_excerpts.summary().text.len;
2154                            edit.old.start += excerpt_old_start;
2155                            edit.old.end += excerpt_old_start;
2156                            edit.new.start += excerpt_new_start;
2157                            edit.new.end += excerpt_new_start;
2158                            edit
2159                        }),
2160                );
2161
2162                new_excerpt = Excerpt::new(
2163                    old_excerpt.id,
2164                    locator.clone(),
2165                    buffer_id,
2166                    buffer.snapshot(),
2167                    old_excerpt.range.clone(),
2168                    old_excerpt.has_trailing_newline,
2169                );
2170            } else {
2171                new_excerpt = old_excerpt.clone();
2172                new_excerpt.buffer = buffer.snapshot();
2173            }
2174
2175            new_excerpts.push(new_excerpt, &());
2176            cursor.next(&());
2177        }
2178        new_excerpts.append(cursor.suffix(&()), &());
2179
2180        drop(cursor);
2181        snapshot.excerpts = new_excerpts;
2182
2183        self.subscriptions.publish(edits);
2184    }
2185}
2186
2187#[cfg(any(test, feature = "test-support"))]
2188impl MultiBuffer {
2189    pub fn build_simple(text: &str, cx: &mut gpui::AppContext) -> Model<Self> {
2190        let buffer = cx.new_model(|cx| Buffer::local(text, cx));
2191        cx.new_model(|cx| Self::singleton(buffer, cx))
2192    }
2193
2194    pub fn build_multi<const COUNT: usize>(
2195        excerpts: [(&str, Vec<Range<Point>>); COUNT],
2196        cx: &mut gpui::AppContext,
2197    ) -> Model<Self> {
2198        let multi = cx.new_model(|_| Self::new(Capability::ReadWrite));
2199        for (text, ranges) in excerpts {
2200            let buffer = cx.new_model(|cx| Buffer::local(text, cx));
2201            let excerpt_ranges = ranges.into_iter().map(|range| ExcerptRange {
2202                context: range,
2203                primary: None,
2204            });
2205            multi.update(cx, |multi, cx| {
2206                multi.push_excerpts(buffer, excerpt_ranges, cx)
2207            });
2208        }
2209
2210        multi
2211    }
2212
2213    pub fn build_from_buffer(buffer: Model<Buffer>, cx: &mut gpui::AppContext) -> Model<Self> {
2214        cx.new_model(|cx| Self::singleton(buffer, cx))
2215    }
2216
2217    pub fn build_random(rng: &mut impl rand::Rng, cx: &mut gpui::AppContext) -> Model<Self> {
2218        cx.new_model(|cx| {
2219            let mut multibuffer = MultiBuffer::new(Capability::ReadWrite);
2220            let mutation_count = rng.gen_range(1..=5);
2221            multibuffer.randomly_edit_excerpts(rng, mutation_count, cx);
2222            multibuffer
2223        })
2224    }
2225
2226    pub fn randomly_edit(
2227        &mut self,
2228        rng: &mut impl rand::Rng,
2229        edit_count: usize,
2230        cx: &mut ModelContext<Self>,
2231    ) {
2232        use util::RandomCharIter;
2233
2234        let snapshot = self.read(cx);
2235        let mut edits: Vec<(Range<usize>, Arc<str>)> = Vec::new();
2236        let mut last_end = None;
2237        for _ in 0..edit_count {
2238            if last_end.map_or(false, |last_end| last_end >= snapshot.len()) {
2239                break;
2240            }
2241
2242            let new_start = last_end.map_or(0, |last_end| last_end + 1);
2243            let end = snapshot.clip_offset(rng.gen_range(new_start..=snapshot.len()), Bias::Right);
2244            let start = snapshot.clip_offset(rng.gen_range(new_start..=end), Bias::Right);
2245            last_end = Some(end);
2246
2247            let mut range = start..end;
2248            if rng.gen_bool(0.2) {
2249                mem::swap(&mut range.start, &mut range.end);
2250            }
2251
2252            let new_text_len = rng.gen_range(0..10);
2253            let new_text: String = RandomCharIter::new(&mut *rng).take(new_text_len).collect();
2254
2255            edits.push((range, new_text.into()));
2256        }
2257        log::info!("mutating multi-buffer with {:?}", edits);
2258        drop(snapshot);
2259
2260        self.edit(edits, None, cx);
2261    }
2262
2263    pub fn randomly_edit_excerpts(
2264        &mut self,
2265        rng: &mut impl rand::Rng,
2266        mutation_count: usize,
2267        cx: &mut ModelContext<Self>,
2268    ) {
2269        use rand::prelude::*;
2270        use std::env;
2271        use util::RandomCharIter;
2272
2273        let max_excerpts = env::var("MAX_EXCERPTS")
2274            .map(|i| i.parse().expect("invalid `MAX_EXCERPTS` variable"))
2275            .unwrap_or(5);
2276
2277        let mut buffers = Vec::new();
2278        for _ in 0..mutation_count {
2279            if rng.gen_bool(0.05) {
2280                log::info!("Clearing multi-buffer");
2281                self.clear(cx);
2282                continue;
2283            } else if rng.gen_bool(0.1) && !self.excerpt_ids().is_empty() {
2284                let ids = self.excerpt_ids();
2285                let mut excerpts = HashSet::default();
2286                for _ in 0..rng.gen_range(0..ids.len()) {
2287                    excerpts.extend(ids.choose(rng).copied());
2288                }
2289
2290                let line_count = rng.gen_range(0..5);
2291
2292                log::info!("Expanding excerpts {excerpts:?} by {line_count} lines");
2293
2294                self.expand_excerpts(
2295                    excerpts.iter().cloned(),
2296                    line_count,
2297                    ExpandExcerptDirection::UpAndDown,
2298                    cx,
2299                );
2300                continue;
2301            }
2302
2303            let excerpt_ids = self.excerpt_ids();
2304            if excerpt_ids.is_empty() || (rng.gen() && excerpt_ids.len() < max_excerpts) {
2305                let buffer_handle = if rng.gen() || self.buffers.borrow().is_empty() {
2306                    let text = RandomCharIter::new(&mut *rng).take(10).collect::<String>();
2307                    buffers.push(cx.new_model(|cx| Buffer::local(text, cx)));
2308                    let buffer = buffers.last().unwrap().read(cx);
2309                    log::info!(
2310                        "Creating new buffer {} with text: {:?}",
2311                        buffer.remote_id(),
2312                        buffer.text()
2313                    );
2314                    buffers.last().unwrap().clone()
2315                } else {
2316                    self.buffers
2317                        .borrow()
2318                        .values()
2319                        .choose(rng)
2320                        .unwrap()
2321                        .buffer
2322                        .clone()
2323                };
2324
2325                let buffer = buffer_handle.read(cx);
2326                let buffer_text = buffer.text();
2327                let ranges = (0..rng.gen_range(0..5))
2328                    .map(|_| {
2329                        let end_ix =
2330                            buffer.clip_offset(rng.gen_range(0..=buffer.len()), Bias::Right);
2331                        let start_ix = buffer.clip_offset(rng.gen_range(0..=end_ix), Bias::Left);
2332                        ExcerptRange {
2333                            context: start_ix..end_ix,
2334                            primary: None,
2335                        }
2336                    })
2337                    .collect::<Vec<_>>();
2338                log::info!(
2339                    "Inserting excerpts from buffer {} and ranges {:?}: {:?}",
2340                    buffer_handle.read(cx).remote_id(),
2341                    ranges.iter().map(|r| &r.context).collect::<Vec<_>>(),
2342                    ranges
2343                        .iter()
2344                        .map(|r| &buffer_text[r.context.clone()])
2345                        .collect::<Vec<_>>()
2346                );
2347
2348                let excerpt_id = self.push_excerpts(buffer_handle.clone(), ranges, cx);
2349                log::info!("Inserted with ids: {:?}", excerpt_id);
2350            } else {
2351                let remove_count = rng.gen_range(1..=excerpt_ids.len());
2352                let mut excerpts_to_remove = excerpt_ids
2353                    .choose_multiple(rng, remove_count)
2354                    .cloned()
2355                    .collect::<Vec<_>>();
2356                let snapshot = self.snapshot.borrow();
2357                excerpts_to_remove.sort_unstable_by(|a, b| a.cmp(b, &snapshot));
2358                drop(snapshot);
2359                log::info!("Removing excerpts {:?}", excerpts_to_remove);
2360                self.remove_excerpts(excerpts_to_remove, cx);
2361            }
2362        }
2363    }
2364
2365    pub fn randomly_mutate(
2366        &mut self,
2367        rng: &mut impl rand::Rng,
2368        mutation_count: usize,
2369        cx: &mut ModelContext<Self>,
2370    ) {
2371        use rand::prelude::*;
2372
2373        if rng.gen_bool(0.7) || self.singleton {
2374            let buffer = self
2375                .buffers
2376                .borrow()
2377                .values()
2378                .choose(rng)
2379                .map(|state| state.buffer.clone());
2380
2381            if let Some(buffer) = buffer {
2382                buffer.update(cx, |buffer, cx| {
2383                    if rng.gen() {
2384                        buffer.randomly_edit(rng, mutation_count, cx);
2385                    } else {
2386                        buffer.randomly_undo_redo(rng, cx);
2387                    }
2388                });
2389            } else {
2390                self.randomly_edit(rng, mutation_count, cx);
2391            }
2392        } else {
2393            self.randomly_edit_excerpts(rng, mutation_count, cx);
2394        }
2395
2396        self.check_invariants(cx);
2397    }
2398
2399    fn check_invariants(&self, cx: &mut ModelContext<Self>) {
2400        let snapshot = self.read(cx);
2401        let excerpts = snapshot.excerpts.items(&());
2402        let excerpt_ids = snapshot.excerpt_ids.items(&());
2403
2404        for (ix, excerpt) in excerpts.iter().enumerate() {
2405            if ix == 0 {
2406                if excerpt.locator <= Locator::min() {
2407                    panic!("invalid first excerpt locator {:?}", excerpt.locator);
2408                }
2409            } else if excerpt.locator <= excerpts[ix - 1].locator {
2410                panic!("excerpts are out-of-order: {:?}", excerpts);
2411            }
2412        }
2413
2414        for (ix, entry) in excerpt_ids.iter().enumerate() {
2415            if ix == 0 {
2416                if entry.id.cmp(&ExcerptId::min(), &snapshot).is_le() {
2417                    panic!("invalid first excerpt id {:?}", entry.id);
2418                }
2419            } else if entry.id <= excerpt_ids[ix - 1].id {
2420                panic!("excerpt ids are out-of-order: {:?}", excerpt_ids);
2421            }
2422        }
2423    }
2424}
2425
2426impl EventEmitter<Event> for MultiBuffer {}
2427
2428impl MultiBufferSnapshot {
2429    pub fn text(&self) -> String {
2430        self.chunks(0..self.len(), false)
2431            .map(|chunk| chunk.text)
2432            .collect()
2433    }
2434
2435    pub fn reversed_chars_at<T: ToOffset>(&self, position: T) -> impl Iterator<Item = char> + '_ {
2436        let mut offset = position.to_offset(self);
2437        let mut cursor = self.excerpts.cursor::<usize>(&());
2438        cursor.seek(&offset, Bias::Left, &());
2439        let mut excerpt_chunks = cursor.item().map(|excerpt| {
2440            let end_before_footer = cursor.start() + excerpt.text_summary.len;
2441            let start = excerpt.range.context.start.to_offset(&excerpt.buffer);
2442            let end = start + (cmp::min(offset, end_before_footer) - cursor.start());
2443            excerpt.buffer.reversed_chunks_in_range(start..end)
2444        });
2445        iter::from_fn(move || {
2446            if offset == *cursor.start() {
2447                cursor.prev(&());
2448                let excerpt = cursor.item()?;
2449                excerpt_chunks = Some(
2450                    excerpt
2451                        .buffer
2452                        .reversed_chunks_in_range(excerpt.range.context.clone()),
2453                );
2454            }
2455
2456            let excerpt = cursor.item().unwrap();
2457            if offset == cursor.end(&()) && excerpt.has_trailing_newline {
2458                offset -= 1;
2459                Some("\n")
2460            } else {
2461                let chunk = excerpt_chunks.as_mut().unwrap().next().unwrap();
2462                offset -= chunk.len();
2463                Some(chunk)
2464            }
2465        })
2466        .flat_map(|c| c.chars().rev())
2467    }
2468
2469    pub fn chars_at<T: ToOffset>(&self, position: T) -> impl Iterator<Item = char> + '_ {
2470        let offset = position.to_offset(self);
2471        self.text_for_range(offset..self.len())
2472            .flat_map(|chunk| chunk.chars())
2473    }
2474
2475    pub fn text_for_range<T: ToOffset>(&self, range: Range<T>) -> impl Iterator<Item = &str> + '_ {
2476        self.chunks(range, false).map(|chunk| chunk.text)
2477    }
2478
2479    pub fn is_line_blank(&self, row: MultiBufferRow) -> bool {
2480        self.text_for_range(Point::new(row.0, 0)..Point::new(row.0, self.line_len(row)))
2481            .all(|chunk| chunk.matches(|c: char| !c.is_whitespace()).next().is_none())
2482    }
2483
2484    pub fn contains_str_at<T>(&self, position: T, needle: &str) -> bool
2485    where
2486        T: ToOffset,
2487    {
2488        let position = position.to_offset(self);
2489        position == self.clip_offset(position, Bias::Left)
2490            && self
2491                .bytes_in_range(position..self.len())
2492                .flatten()
2493                .copied()
2494                .take(needle.len())
2495                .eq(needle.bytes())
2496    }
2497
2498    pub fn surrounding_word<T: ToOffset>(
2499        &self,
2500        start: T,
2501        for_completion: bool,
2502    ) -> (Range<usize>, Option<CharKind>) {
2503        let mut start = start.to_offset(self);
2504        let mut end = start;
2505        let mut next_chars = self.chars_at(start).peekable();
2506        let mut prev_chars = self.reversed_chars_at(start).peekable();
2507
2508        let classifier = self
2509            .char_classifier_at(start)
2510            .for_completion(for_completion);
2511
2512        let word_kind = cmp::max(
2513            prev_chars.peek().copied().map(|c| classifier.kind(c)),
2514            next_chars.peek().copied().map(|c| classifier.kind(c)),
2515        );
2516
2517        for ch in prev_chars {
2518            if Some(classifier.kind(ch)) == word_kind && ch != '\n' {
2519                start -= ch.len_utf8();
2520            } else {
2521                break;
2522            }
2523        }
2524
2525        for ch in next_chars {
2526            if Some(classifier.kind(ch)) == word_kind && ch != '\n' {
2527                end += ch.len_utf8();
2528            } else {
2529                break;
2530            }
2531        }
2532
2533        (start..end, word_kind)
2534    }
2535
2536    pub fn as_singleton(&self) -> Option<(&ExcerptId, BufferId, &BufferSnapshot)> {
2537        if self.singleton {
2538            self.excerpts
2539                .iter()
2540                .next()
2541                .map(|e| (&e.id, e.buffer_id, &e.buffer))
2542        } else {
2543            None
2544        }
2545    }
2546
2547    pub fn len(&self) -> usize {
2548        self.excerpts.summary().text.len
2549    }
2550
2551    pub fn is_empty(&self) -> bool {
2552        self.excerpts.summary().text.len == 0
2553    }
2554
2555    pub fn widest_line_number(&self) -> u32 {
2556        self.excerpts.summary().widest_line_number + 1
2557    }
2558
2559    pub fn clip_offset(&self, offset: usize, bias: Bias) -> usize {
2560        if let Some((_, _, buffer)) = self.as_singleton() {
2561            return buffer.clip_offset(offset, bias);
2562        }
2563
2564        let mut cursor = self.excerpts.cursor::<usize>(&());
2565        cursor.seek(&offset, Bias::Right, &());
2566        let overshoot = if let Some(excerpt) = cursor.item() {
2567            let excerpt_start = excerpt.range.context.start.to_offset(&excerpt.buffer);
2568            let buffer_offset = excerpt
2569                .buffer
2570                .clip_offset(excerpt_start + (offset - cursor.start()), bias);
2571            buffer_offset.saturating_sub(excerpt_start)
2572        } else {
2573            0
2574        };
2575        cursor.start() + overshoot
2576    }
2577
2578    pub fn clip_point(&self, point: Point, bias: Bias) -> Point {
2579        if let Some((_, _, buffer)) = self.as_singleton() {
2580            return buffer.clip_point(point, bias);
2581        }
2582
2583        let mut cursor = self.excerpts.cursor::<Point>(&());
2584        cursor.seek(&point, Bias::Right, &());
2585        let overshoot = if let Some(excerpt) = cursor.item() {
2586            let excerpt_start = excerpt.range.context.start.to_point(&excerpt.buffer);
2587            let buffer_point = excerpt
2588                .buffer
2589                .clip_point(excerpt_start + (point - cursor.start()), bias);
2590            buffer_point.saturating_sub(excerpt_start)
2591        } else {
2592            Point::zero()
2593        };
2594        *cursor.start() + overshoot
2595    }
2596
2597    pub fn clip_offset_utf16(&self, offset: OffsetUtf16, bias: Bias) -> OffsetUtf16 {
2598        if let Some((_, _, buffer)) = self.as_singleton() {
2599            return buffer.clip_offset_utf16(offset, bias);
2600        }
2601
2602        let mut cursor = self.excerpts.cursor::<OffsetUtf16>(&());
2603        cursor.seek(&offset, Bias::Right, &());
2604        let overshoot = if let Some(excerpt) = cursor.item() {
2605            let excerpt_start = excerpt.range.context.start.to_offset_utf16(&excerpt.buffer);
2606            let buffer_offset = excerpt
2607                .buffer
2608                .clip_offset_utf16(excerpt_start + (offset - cursor.start()), bias);
2609            OffsetUtf16(buffer_offset.0.saturating_sub(excerpt_start.0))
2610        } else {
2611            OffsetUtf16(0)
2612        };
2613        *cursor.start() + overshoot
2614    }
2615
2616    pub fn clip_point_utf16(&self, point: Unclipped<PointUtf16>, bias: Bias) -> PointUtf16 {
2617        if let Some((_, _, buffer)) = self.as_singleton() {
2618            return buffer.clip_point_utf16(point, bias);
2619        }
2620
2621        let mut cursor = self.excerpts.cursor::<PointUtf16>(&());
2622        cursor.seek(&point.0, Bias::Right, &());
2623        let overshoot = if let Some(excerpt) = cursor.item() {
2624            let excerpt_start = excerpt
2625                .buffer
2626                .offset_to_point_utf16(excerpt.range.context.start.to_offset(&excerpt.buffer));
2627            let buffer_point = excerpt
2628                .buffer
2629                .clip_point_utf16(Unclipped(excerpt_start + (point.0 - cursor.start())), bias);
2630            buffer_point.saturating_sub(excerpt_start)
2631        } else {
2632            PointUtf16::zero()
2633        };
2634        *cursor.start() + overshoot
2635    }
2636
2637    pub fn bytes_in_range<T: ToOffset>(&self, range: Range<T>) -> MultiBufferBytes {
2638        let range = range.start.to_offset(self)..range.end.to_offset(self);
2639        let mut excerpts = self.excerpts.cursor::<usize>(&());
2640        excerpts.seek(&range.start, Bias::Right, &());
2641
2642        let mut chunk = &[][..];
2643        let excerpt_bytes = if let Some(excerpt) = excerpts.item() {
2644            let mut excerpt_bytes = excerpt
2645                .bytes_in_range(range.start - excerpts.start()..range.end - excerpts.start());
2646            chunk = excerpt_bytes.next().unwrap_or(&[][..]);
2647            Some(excerpt_bytes)
2648        } else {
2649            None
2650        };
2651        MultiBufferBytes {
2652            range,
2653            excerpts,
2654            excerpt_bytes,
2655            chunk,
2656        }
2657    }
2658
2659    pub fn reversed_bytes_in_range<T: ToOffset>(
2660        &self,
2661        range: Range<T>,
2662    ) -> ReversedMultiBufferBytes {
2663        let range = range.start.to_offset(self)..range.end.to_offset(self);
2664        let mut excerpts = self.excerpts.cursor::<usize>(&());
2665        excerpts.seek(&range.end, Bias::Left, &());
2666
2667        let mut chunk = &[][..];
2668        let excerpt_bytes = if let Some(excerpt) = excerpts.item() {
2669            let mut excerpt_bytes = excerpt.reversed_bytes_in_range(
2670                range.start.saturating_sub(*excerpts.start())..range.end - *excerpts.start(),
2671            );
2672            chunk = excerpt_bytes.next().unwrap_or(&[][..]);
2673            Some(excerpt_bytes)
2674        } else {
2675            None
2676        };
2677
2678        ReversedMultiBufferBytes {
2679            range,
2680            excerpts,
2681            excerpt_bytes,
2682            chunk,
2683        }
2684    }
2685
2686    pub fn buffer_rows(&self, start_row: MultiBufferRow) -> MultiBufferRows {
2687        let mut result = MultiBufferRows {
2688            buffer_row_range: 0..0,
2689            excerpts: self.excerpts.cursor(&()),
2690        };
2691        result.seek(start_row);
2692        result
2693    }
2694
2695    pub fn chunks<T: ToOffset>(&self, range: Range<T>, language_aware: bool) -> MultiBufferChunks {
2696        let range = range.start.to_offset(self)..range.end.to_offset(self);
2697        let mut chunks = MultiBufferChunks {
2698            range: range.clone(),
2699            excerpts: self.excerpts.cursor(&()),
2700            excerpt_chunks: None,
2701            language_aware,
2702        };
2703        chunks.seek(range);
2704        chunks
2705    }
2706
2707    pub fn offset_to_point(&self, offset: usize) -> Point {
2708        if let Some((_, _, buffer)) = self.as_singleton() {
2709            return buffer.offset_to_point(offset);
2710        }
2711
2712        let mut cursor = self.excerpts.cursor::<(usize, Point)>(&());
2713        cursor.seek(&offset, Bias::Right, &());
2714        if let Some(excerpt) = cursor.item() {
2715            let (start_offset, start_point) = cursor.start();
2716            let overshoot = offset - start_offset;
2717            let excerpt_start_offset = excerpt.range.context.start.to_offset(&excerpt.buffer);
2718            let excerpt_start_point = excerpt.range.context.start.to_point(&excerpt.buffer);
2719            let buffer_point = excerpt
2720                .buffer
2721                .offset_to_point(excerpt_start_offset + overshoot);
2722            *start_point + (buffer_point - excerpt_start_point)
2723        } else {
2724            self.excerpts.summary().text.lines
2725        }
2726    }
2727
2728    pub fn offset_to_point_utf16(&self, offset: usize) -> PointUtf16 {
2729        if let Some((_, _, buffer)) = self.as_singleton() {
2730            return buffer.offset_to_point_utf16(offset);
2731        }
2732
2733        let mut cursor = self.excerpts.cursor::<(usize, PointUtf16)>(&());
2734        cursor.seek(&offset, Bias::Right, &());
2735        if let Some(excerpt) = cursor.item() {
2736            let (start_offset, start_point) = cursor.start();
2737            let overshoot = offset - start_offset;
2738            let excerpt_start_offset = excerpt.range.context.start.to_offset(&excerpt.buffer);
2739            let excerpt_start_point = excerpt.range.context.start.to_point_utf16(&excerpt.buffer);
2740            let buffer_point = excerpt
2741                .buffer
2742                .offset_to_point_utf16(excerpt_start_offset + overshoot);
2743            *start_point + (buffer_point - excerpt_start_point)
2744        } else {
2745            self.excerpts.summary().text.lines_utf16()
2746        }
2747    }
2748
2749    pub fn point_to_point_utf16(&self, point: Point) -> PointUtf16 {
2750        if let Some((_, _, buffer)) = self.as_singleton() {
2751            return buffer.point_to_point_utf16(point);
2752        }
2753
2754        let mut cursor = self.excerpts.cursor::<(Point, PointUtf16)>(&());
2755        cursor.seek(&point, Bias::Right, &());
2756        if let Some(excerpt) = cursor.item() {
2757            let (start_offset, start_point) = cursor.start();
2758            let overshoot = point - start_offset;
2759            let excerpt_start_point = excerpt.range.context.start.to_point(&excerpt.buffer);
2760            let excerpt_start_point_utf16 =
2761                excerpt.range.context.start.to_point_utf16(&excerpt.buffer);
2762            let buffer_point = excerpt
2763                .buffer
2764                .point_to_point_utf16(excerpt_start_point + overshoot);
2765            *start_point + (buffer_point - excerpt_start_point_utf16)
2766        } else {
2767            self.excerpts.summary().text.lines_utf16()
2768        }
2769    }
2770
2771    pub fn point_to_offset(&self, point: Point) -> usize {
2772        if let Some((_, _, buffer)) = self.as_singleton() {
2773            return buffer.point_to_offset(point);
2774        }
2775
2776        let mut cursor = self.excerpts.cursor::<(Point, usize)>(&());
2777        cursor.seek(&point, Bias::Right, &());
2778        if let Some(excerpt) = cursor.item() {
2779            let (start_point, start_offset) = cursor.start();
2780            let overshoot = point - start_point;
2781            let excerpt_start_offset = excerpt.range.context.start.to_offset(&excerpt.buffer);
2782            let excerpt_start_point = excerpt.range.context.start.to_point(&excerpt.buffer);
2783            let buffer_offset = excerpt
2784                .buffer
2785                .point_to_offset(excerpt_start_point + overshoot);
2786            *start_offset + buffer_offset - excerpt_start_offset
2787        } else {
2788            self.excerpts.summary().text.len
2789        }
2790    }
2791
2792    pub fn offset_utf16_to_offset(&self, offset_utf16: OffsetUtf16) -> usize {
2793        if let Some((_, _, buffer)) = self.as_singleton() {
2794            return buffer.offset_utf16_to_offset(offset_utf16);
2795        }
2796
2797        let mut cursor = self.excerpts.cursor::<(OffsetUtf16, usize)>(&());
2798        cursor.seek(&offset_utf16, Bias::Right, &());
2799        if let Some(excerpt) = cursor.item() {
2800            let (start_offset_utf16, start_offset) = cursor.start();
2801            let overshoot = offset_utf16 - start_offset_utf16;
2802            let excerpt_start_offset = excerpt.range.context.start.to_offset(&excerpt.buffer);
2803            let excerpt_start_offset_utf16 =
2804                excerpt.buffer.offset_to_offset_utf16(excerpt_start_offset);
2805            let buffer_offset = excerpt
2806                .buffer
2807                .offset_utf16_to_offset(excerpt_start_offset_utf16 + overshoot);
2808            *start_offset + (buffer_offset - excerpt_start_offset)
2809        } else {
2810            self.excerpts.summary().text.len
2811        }
2812    }
2813
2814    pub fn offset_to_offset_utf16(&self, offset: usize) -> OffsetUtf16 {
2815        if let Some((_, _, buffer)) = self.as_singleton() {
2816            return buffer.offset_to_offset_utf16(offset);
2817        }
2818
2819        let mut cursor = self.excerpts.cursor::<(usize, OffsetUtf16)>(&());
2820        cursor.seek(&offset, Bias::Right, &());
2821        if let Some(excerpt) = cursor.item() {
2822            let (start_offset, start_offset_utf16) = cursor.start();
2823            let overshoot = offset - start_offset;
2824            let excerpt_start_offset_utf16 =
2825                excerpt.range.context.start.to_offset_utf16(&excerpt.buffer);
2826            let excerpt_start_offset = excerpt
2827                .buffer
2828                .offset_utf16_to_offset(excerpt_start_offset_utf16);
2829            let buffer_offset_utf16 = excerpt
2830                .buffer
2831                .offset_to_offset_utf16(excerpt_start_offset + overshoot);
2832            *start_offset_utf16 + (buffer_offset_utf16 - excerpt_start_offset_utf16)
2833        } else {
2834            self.excerpts.summary().text.len_utf16
2835        }
2836    }
2837
2838    pub fn point_utf16_to_offset(&self, point: PointUtf16) -> usize {
2839        if let Some((_, _, buffer)) = self.as_singleton() {
2840            return buffer.point_utf16_to_offset(point);
2841        }
2842
2843        let mut cursor = self.excerpts.cursor::<(PointUtf16, usize)>(&());
2844        cursor.seek(&point, Bias::Right, &());
2845        if let Some(excerpt) = cursor.item() {
2846            let (start_point, start_offset) = cursor.start();
2847            let overshoot = point - start_point;
2848            let excerpt_start_offset = excerpt.range.context.start.to_offset(&excerpt.buffer);
2849            let excerpt_start_point = excerpt
2850                .buffer
2851                .offset_to_point_utf16(excerpt.range.context.start.to_offset(&excerpt.buffer));
2852            let buffer_offset = excerpt
2853                .buffer
2854                .point_utf16_to_offset(excerpt_start_point + overshoot);
2855            *start_offset + (buffer_offset - excerpt_start_offset)
2856        } else {
2857            self.excerpts.summary().text.len
2858        }
2859    }
2860
2861    pub fn point_to_buffer_offset<T: ToOffset>(
2862        &self,
2863        point: T,
2864    ) -> Option<(&BufferSnapshot, usize)> {
2865        let offset = point.to_offset(self);
2866        let mut cursor = self.excerpts.cursor::<usize>(&());
2867        cursor.seek(&offset, Bias::Right, &());
2868        if cursor.item().is_none() {
2869            cursor.prev(&());
2870        }
2871
2872        cursor.item().map(|excerpt| {
2873            let excerpt_start = excerpt.range.context.start.to_offset(&excerpt.buffer);
2874            let buffer_point = excerpt_start + offset - *cursor.start();
2875            (&excerpt.buffer, buffer_point)
2876        })
2877    }
2878
2879    pub fn suggested_indents(
2880        &self,
2881        rows: impl IntoIterator<Item = u32>,
2882        cx: &AppContext,
2883    ) -> BTreeMap<MultiBufferRow, IndentSize> {
2884        let mut result = BTreeMap::new();
2885
2886        let mut rows_for_excerpt = Vec::new();
2887        let mut cursor = self.excerpts.cursor::<Point>(&());
2888        let mut rows = rows.into_iter().peekable();
2889        let mut prev_row = u32::MAX;
2890        let mut prev_language_indent_size = IndentSize::default();
2891
2892        while let Some(row) = rows.next() {
2893            cursor.seek(&Point::new(row, 0), Bias::Right, &());
2894            let excerpt = match cursor.item() {
2895                Some(excerpt) => excerpt,
2896                _ => continue,
2897            };
2898
2899            // Retrieve the language and indent size once for each disjoint region being indented.
2900            let single_indent_size = if row.saturating_sub(1) == prev_row {
2901                prev_language_indent_size
2902            } else {
2903                excerpt
2904                    .buffer
2905                    .language_indent_size_at(Point::new(row, 0), cx)
2906            };
2907            prev_language_indent_size = single_indent_size;
2908            prev_row = row;
2909
2910            let start_buffer_row = excerpt.range.context.start.to_point(&excerpt.buffer).row;
2911            let start_multibuffer_row = cursor.start().row;
2912
2913            rows_for_excerpt.push(row);
2914            while let Some(next_row) = rows.peek().copied() {
2915                if cursor.end(&()).row > next_row {
2916                    rows_for_excerpt.push(next_row);
2917                    rows.next();
2918                } else {
2919                    break;
2920                }
2921            }
2922
2923            let buffer_rows = rows_for_excerpt
2924                .drain(..)
2925                .map(|row| start_buffer_row + row - start_multibuffer_row);
2926            let buffer_indents = excerpt
2927                .buffer
2928                .suggested_indents(buffer_rows, single_indent_size);
2929            let multibuffer_indents = buffer_indents.into_iter().map(|(row, indent)| {
2930                (
2931                    MultiBufferRow(start_multibuffer_row + row - start_buffer_row),
2932                    indent,
2933                )
2934            });
2935            result.extend(multibuffer_indents);
2936        }
2937
2938        result
2939    }
2940
2941    pub fn indent_size_for_line(&self, row: MultiBufferRow) -> IndentSize {
2942        if let Some((buffer, range)) = self.buffer_line_for_row(row) {
2943            let mut size = buffer.indent_size_for_line(range.start.row);
2944            size.len = size
2945                .len
2946                .min(range.end.column)
2947                .saturating_sub(range.start.column);
2948            size
2949        } else {
2950            IndentSize::spaces(0)
2951        }
2952    }
2953
2954    pub fn indent_and_comment_for_line(&self, row: MultiBufferRow, cx: &AppContext) -> String {
2955        let mut indent = self.indent_size_for_line(row).chars().collect::<String>();
2956
2957        if self.settings_at(0, cx).extend_comment_on_newline {
2958            if let Some(language_scope) = self.language_scope_at(Point::new(row.0, 0)) {
2959                let delimiters = language_scope.line_comment_prefixes();
2960                for delimiter in delimiters {
2961                    if *self
2962                        .chars_at(Point::new(row.0, indent.len() as u32))
2963                        .take(delimiter.chars().count())
2964                        .collect::<String>()
2965                        .as_str()
2966                        == **delimiter
2967                    {
2968                        indent.push_str(&delimiter);
2969                        break;
2970                    }
2971                }
2972            }
2973        }
2974
2975        indent
2976    }
2977
2978    pub fn prev_non_blank_row(&self, mut row: MultiBufferRow) -> Option<MultiBufferRow> {
2979        while row.0 > 0 {
2980            row.0 -= 1;
2981            if !self.is_line_blank(row) {
2982                return Some(row);
2983            }
2984        }
2985        None
2986    }
2987
2988    pub fn line_len(&self, row: MultiBufferRow) -> u32 {
2989        if let Some((_, range)) = self.buffer_line_for_row(row) {
2990            range.end.column - range.start.column
2991        } else {
2992            0
2993        }
2994    }
2995
2996    pub fn buffer_line_for_row(
2997        &self,
2998        row: MultiBufferRow,
2999    ) -> Option<(&BufferSnapshot, Range<Point>)> {
3000        let mut cursor = self.excerpts.cursor::<Point>(&());
3001        let point = Point::new(row.0, 0);
3002        cursor.seek(&point, Bias::Right, &());
3003        if cursor.item().is_none() && *cursor.start() == point {
3004            cursor.prev(&());
3005        }
3006        if let Some(excerpt) = cursor.item() {
3007            let overshoot = row.0 - cursor.start().row;
3008            let excerpt_start = excerpt.range.context.start.to_point(&excerpt.buffer);
3009            let excerpt_end = excerpt.range.context.end.to_point(&excerpt.buffer);
3010            let buffer_row = excerpt_start.row + overshoot;
3011            let line_start = Point::new(buffer_row, 0);
3012            let line_end = Point::new(buffer_row, excerpt.buffer.line_len(buffer_row));
3013            return Some((
3014                &excerpt.buffer,
3015                line_start.max(excerpt_start)..line_end.min(excerpt_end),
3016            ));
3017        }
3018        None
3019    }
3020
3021    pub fn max_point(&self) -> Point {
3022        self.text_summary().lines
3023    }
3024
3025    pub fn max_row(&self) -> MultiBufferRow {
3026        MultiBufferRow(self.text_summary().lines.row)
3027    }
3028
3029    pub fn text_summary(&self) -> TextSummary {
3030        self.excerpts.summary().text.clone()
3031    }
3032
3033    pub fn text_summary_for_range<D, O>(&self, range: Range<O>) -> D
3034    where
3035        D: TextDimension,
3036        O: ToOffset,
3037    {
3038        let mut summary = D::zero(&());
3039        let mut range = range.start.to_offset(self)..range.end.to_offset(self);
3040        let mut cursor = self.excerpts.cursor::<usize>(&());
3041        cursor.seek(&range.start, Bias::Right, &());
3042        if let Some(excerpt) = cursor.item() {
3043            let mut end_before_newline = cursor.end(&());
3044            if excerpt.has_trailing_newline {
3045                end_before_newline -= 1;
3046            }
3047
3048            let excerpt_start = excerpt.range.context.start.to_offset(&excerpt.buffer);
3049            let start_in_excerpt = excerpt_start + (range.start - cursor.start());
3050            let end_in_excerpt =
3051                excerpt_start + (cmp::min(end_before_newline, range.end) - cursor.start());
3052            summary.add_assign(
3053                &excerpt
3054                    .buffer
3055                    .text_summary_for_range(start_in_excerpt..end_in_excerpt),
3056            );
3057
3058            if range.end > end_before_newline {
3059                summary.add_assign(&D::from_text_summary(&TextSummary::from("\n")));
3060            }
3061
3062            cursor.next(&());
3063        }
3064
3065        if range.end > *cursor.start() {
3066            summary.add_assign(&D::from_text_summary(&cursor.summary::<_, TextSummary>(
3067                &range.end,
3068                Bias::Right,
3069                &(),
3070            )));
3071            if let Some(excerpt) = cursor.item() {
3072                range.end = cmp::max(*cursor.start(), range.end);
3073
3074                let excerpt_start = excerpt.range.context.start.to_offset(&excerpt.buffer);
3075                let end_in_excerpt = excerpt_start + (range.end - cursor.start());
3076                summary.add_assign(
3077                    &excerpt
3078                        .buffer
3079                        .text_summary_for_range(excerpt_start..end_in_excerpt),
3080                );
3081            }
3082        }
3083
3084        summary
3085    }
3086
3087    pub fn summary_for_anchor<D>(&self, anchor: &Anchor) -> D
3088    where
3089        D: TextDimension + Ord + Sub<D, Output = D>,
3090    {
3091        let mut cursor = self.excerpts.cursor::<ExcerptSummary>(&());
3092        let locator = self.excerpt_locator_for_id(anchor.excerpt_id);
3093
3094        cursor.seek(locator, Bias::Left, &());
3095        if cursor.item().is_none() {
3096            cursor.next(&());
3097        }
3098
3099        let mut position = D::from_text_summary(&cursor.start().text);
3100        if let Some(excerpt) = cursor.item() {
3101            if excerpt.id == anchor.excerpt_id {
3102                let excerpt_buffer_start =
3103                    excerpt.range.context.start.summary::<D>(&excerpt.buffer);
3104                let excerpt_buffer_end = excerpt.range.context.end.summary::<D>(&excerpt.buffer);
3105                let buffer_position = cmp::min(
3106                    excerpt_buffer_end,
3107                    anchor.text_anchor.summary::<D>(&excerpt.buffer),
3108                );
3109                if buffer_position > excerpt_buffer_start {
3110                    position.add_assign(&(buffer_position - excerpt_buffer_start));
3111                }
3112            }
3113        }
3114        position
3115    }
3116
3117    pub fn summaries_for_anchors<'a, D, I>(&'a self, anchors: I) -> Vec<D>
3118    where
3119        D: TextDimension + Ord + Sub<D, Output = D>,
3120        I: 'a + IntoIterator<Item = &'a Anchor>,
3121    {
3122        if let Some((_, _, buffer)) = self.as_singleton() {
3123            return buffer
3124                .summaries_for_anchors(anchors.into_iter().map(|a| &a.text_anchor))
3125                .collect();
3126        }
3127
3128        let mut anchors = anchors.into_iter().peekable();
3129        let mut cursor = self.excerpts.cursor::<ExcerptSummary>(&());
3130        let mut summaries = Vec::new();
3131        while let Some(anchor) = anchors.peek() {
3132            let excerpt_id = anchor.excerpt_id;
3133            let excerpt_anchors = iter::from_fn(|| {
3134                let anchor = anchors.peek()?;
3135                if anchor.excerpt_id == excerpt_id {
3136                    Some(&anchors.next().unwrap().text_anchor)
3137                } else {
3138                    None
3139                }
3140            });
3141
3142            let locator = self.excerpt_locator_for_id(excerpt_id);
3143            cursor.seek_forward(locator, Bias::Left, &());
3144            if cursor.item().is_none() {
3145                cursor.next(&());
3146            }
3147
3148            let position = D::from_text_summary(&cursor.start().text);
3149            if let Some(excerpt) = cursor.item() {
3150                if excerpt.id == excerpt_id {
3151                    let excerpt_buffer_start =
3152                        excerpt.range.context.start.summary::<D>(&excerpt.buffer);
3153                    let excerpt_buffer_end =
3154                        excerpt.range.context.end.summary::<D>(&excerpt.buffer);
3155                    summaries.extend(
3156                        excerpt
3157                            .buffer
3158                            .summaries_for_anchors::<D, _>(excerpt_anchors)
3159                            .map(move |summary| {
3160                                let summary = cmp::min(excerpt_buffer_end.clone(), summary);
3161                                let mut position = position.clone();
3162                                let excerpt_buffer_start = excerpt_buffer_start.clone();
3163                                if summary > excerpt_buffer_start {
3164                                    position.add_assign(&(summary - excerpt_buffer_start));
3165                                }
3166                                position
3167                            }),
3168                    );
3169                    continue;
3170                }
3171            }
3172
3173            summaries.extend(excerpt_anchors.map(|_| position.clone()));
3174        }
3175
3176        summaries
3177    }
3178
3179    pub fn dimensions_from_points<'a, D>(
3180        &'a self,
3181        points: impl 'a + IntoIterator<Item = Point>,
3182    ) -> impl 'a + Iterator<Item = D>
3183    where
3184        D: TextDimension,
3185    {
3186        let mut cursor = self.excerpts.cursor::<TextSummary>(&());
3187        let mut memoized_source_start: Option<Point> = None;
3188        let mut points = points.into_iter();
3189        std::iter::from_fn(move || {
3190            let point = points.next()?;
3191
3192            // Clear the memoized source start if the point is in a different excerpt than previous.
3193            if memoized_source_start.map_or(false, |_| point >= cursor.end(&()).lines) {
3194                memoized_source_start = None;
3195            }
3196
3197            // Now determine where the excerpt containing the point starts in its source buffer.
3198            // We'll use this value to calculate overshoot next.
3199            let source_start = if let Some(source_start) = memoized_source_start {
3200                source_start
3201            } else {
3202                cursor.seek_forward(&point, Bias::Right, &());
3203                if let Some(excerpt) = cursor.item() {
3204                    let source_start = excerpt.range.context.start.to_point(&excerpt.buffer);
3205                    memoized_source_start = Some(source_start);
3206                    source_start
3207                } else {
3208                    return Some(D::from_text_summary(cursor.start()));
3209                }
3210            };
3211
3212            // First, assume the output dimension is at least the start of the excerpt containing the point
3213            let mut output = D::from_text_summary(cursor.start());
3214
3215            // If the point lands within its excerpt, calculate and add the overshoot in dimension D.
3216            if let Some(excerpt) = cursor.item() {
3217                let overshoot = point - cursor.start().lines;
3218                if !overshoot.is_zero() {
3219                    let end_in_excerpt = source_start + overshoot;
3220                    output.add_assign(
3221                        &excerpt
3222                            .buffer
3223                            .text_summary_for_range::<D, _>(source_start..end_in_excerpt),
3224                    );
3225                }
3226            }
3227            Some(output)
3228        })
3229    }
3230
3231    pub fn refresh_anchors<'a, I>(&'a self, anchors: I) -> Vec<(usize, Anchor, bool)>
3232    where
3233        I: 'a + IntoIterator<Item = &'a Anchor>,
3234    {
3235        let mut anchors = anchors.into_iter().enumerate().peekable();
3236        let mut cursor = self.excerpts.cursor::<Option<&Locator>>(&());
3237        cursor.next(&());
3238
3239        let mut result = Vec::new();
3240
3241        while let Some((_, anchor)) = anchors.peek() {
3242            let old_excerpt_id = anchor.excerpt_id;
3243
3244            // Find the location where this anchor's excerpt should be.
3245            let old_locator = self.excerpt_locator_for_id(old_excerpt_id);
3246            cursor.seek_forward(&Some(old_locator), Bias::Left, &());
3247
3248            if cursor.item().is_none() {
3249                cursor.next(&());
3250            }
3251
3252            let next_excerpt = cursor.item();
3253            let prev_excerpt = cursor.prev_item();
3254
3255            // Process all of the anchors for this excerpt.
3256            while let Some((_, anchor)) = anchors.peek() {
3257                if anchor.excerpt_id != old_excerpt_id {
3258                    break;
3259                }
3260                let (anchor_ix, anchor) = anchors.next().unwrap();
3261                let mut anchor = *anchor;
3262
3263                // Leave min and max anchors unchanged if invalid or
3264                // if the old excerpt still exists at this location
3265                let mut kept_position = next_excerpt
3266                    .map_or(false, |e| e.id == old_excerpt_id && e.contains(&anchor))
3267                    || old_excerpt_id == ExcerptId::max()
3268                    || old_excerpt_id == ExcerptId::min();
3269
3270                // If the old excerpt no longer exists at this location, then attempt to
3271                // find an equivalent position for this anchor in an adjacent excerpt.
3272                if !kept_position {
3273                    for excerpt in [next_excerpt, prev_excerpt].iter().filter_map(|e| *e) {
3274                        if excerpt.contains(&anchor) {
3275                            anchor.excerpt_id = excerpt.id;
3276                            kept_position = true;
3277                            break;
3278                        }
3279                    }
3280                }
3281
3282                // If there's no adjacent excerpt that contains the anchor's position,
3283                // then report that the anchor has lost its position.
3284                if !kept_position {
3285                    anchor = if let Some(excerpt) = next_excerpt {
3286                        let mut text_anchor = excerpt
3287                            .range
3288                            .context
3289                            .start
3290                            .bias(anchor.text_anchor.bias, &excerpt.buffer);
3291                        if text_anchor
3292                            .cmp(&excerpt.range.context.end, &excerpt.buffer)
3293                            .is_gt()
3294                        {
3295                            text_anchor = excerpt.range.context.end;
3296                        }
3297                        Anchor {
3298                            buffer_id: Some(excerpt.buffer_id),
3299                            excerpt_id: excerpt.id,
3300                            text_anchor,
3301                        }
3302                    } else if let Some(excerpt) = prev_excerpt {
3303                        let mut text_anchor = excerpt
3304                            .range
3305                            .context
3306                            .end
3307                            .bias(anchor.text_anchor.bias, &excerpt.buffer);
3308                        if text_anchor
3309                            .cmp(&excerpt.range.context.start, &excerpt.buffer)
3310                            .is_lt()
3311                        {
3312                            text_anchor = excerpt.range.context.start;
3313                        }
3314                        Anchor {
3315                            buffer_id: Some(excerpt.buffer_id),
3316                            excerpt_id: excerpt.id,
3317                            text_anchor,
3318                        }
3319                    } else if anchor.text_anchor.bias == Bias::Left {
3320                        Anchor::min()
3321                    } else {
3322                        Anchor::max()
3323                    };
3324                }
3325
3326                result.push((anchor_ix, anchor, kept_position));
3327            }
3328        }
3329        result.sort_unstable_by(|a, b| a.1.cmp(&b.1, self));
3330        result
3331    }
3332
3333    pub fn anchor_before<T: ToOffset>(&self, position: T) -> Anchor {
3334        self.anchor_at(position, Bias::Left)
3335    }
3336
3337    pub fn anchor_after<T: ToOffset>(&self, position: T) -> Anchor {
3338        self.anchor_at(position, Bias::Right)
3339    }
3340
3341    pub fn anchor_at<T: ToOffset>(&self, position: T, mut bias: Bias) -> Anchor {
3342        let offset = position.to_offset(self);
3343        if let Some((excerpt_id, buffer_id, buffer)) = self.as_singleton() {
3344            return Anchor {
3345                buffer_id: Some(buffer_id),
3346                excerpt_id: *excerpt_id,
3347                text_anchor: buffer.anchor_at(offset, bias),
3348            };
3349        }
3350
3351        let mut cursor = self.excerpts.cursor::<(usize, Option<ExcerptId>)>(&());
3352        cursor.seek(&offset, Bias::Right, &());
3353        if cursor.item().is_none() && offset == cursor.start().0 && bias == Bias::Left {
3354            cursor.prev(&());
3355        }
3356        if let Some(excerpt) = cursor.item() {
3357            let mut overshoot = offset.saturating_sub(cursor.start().0);
3358            if excerpt.has_trailing_newline && offset == cursor.end(&()).0 {
3359                overshoot -= 1;
3360                bias = Bias::Right;
3361            }
3362
3363            let buffer_start = excerpt.range.context.start.to_offset(&excerpt.buffer);
3364            let text_anchor =
3365                excerpt.clip_anchor(excerpt.buffer.anchor_at(buffer_start + overshoot, bias));
3366            Anchor {
3367                buffer_id: Some(excerpt.buffer_id),
3368                excerpt_id: excerpt.id,
3369                text_anchor,
3370            }
3371        } else if offset == 0 && bias == Bias::Left {
3372            Anchor::min()
3373        } else {
3374            Anchor::max()
3375        }
3376    }
3377
3378    /// Returns an anchor for the given excerpt and text anchor,
3379    /// returns None if the excerpt_id is no longer valid.
3380    pub fn anchor_in_excerpt(
3381        &self,
3382        excerpt_id: ExcerptId,
3383        text_anchor: text::Anchor,
3384    ) -> Option<Anchor> {
3385        let locator = self.excerpt_locator_for_id(excerpt_id);
3386        let mut cursor = self.excerpts.cursor::<Option<&Locator>>(&());
3387        cursor.seek(locator, Bias::Left, &());
3388        if let Some(excerpt) = cursor.item() {
3389            if excerpt.id == excerpt_id {
3390                let text_anchor = excerpt.clip_anchor(text_anchor);
3391                drop(cursor);
3392                return Some(Anchor {
3393                    buffer_id: Some(excerpt.buffer_id),
3394                    excerpt_id,
3395                    text_anchor,
3396                });
3397            }
3398        }
3399        None
3400    }
3401
3402    pub fn context_range_for_excerpt(&self, excerpt_id: ExcerptId) -> Option<Range<text::Anchor>> {
3403        Some(self.excerpt(excerpt_id)?.range.context.clone())
3404    }
3405
3406    pub fn can_resolve(&self, anchor: &Anchor) -> bool {
3407        if anchor.excerpt_id == ExcerptId::min() || anchor.excerpt_id == ExcerptId::max() {
3408            true
3409        } else if let Some(excerpt) = self.excerpt(anchor.excerpt_id) {
3410            excerpt.buffer.can_resolve(&anchor.text_anchor)
3411        } else {
3412            false
3413        }
3414    }
3415
3416    pub fn buffer_ids_in_selected_rows(
3417        &self,
3418        selection: Selection<Point>,
3419    ) -> impl Iterator<Item = BufferId> + '_ {
3420        let mut cursor = self.excerpts.cursor::<Point>(&());
3421        cursor.seek(&Point::new(selection.start.row, 0), Bias::Right, &());
3422        cursor.prev(&());
3423
3424        iter::from_fn(move || {
3425            cursor.next(&());
3426            if cursor.start().row <= selection.end.row {
3427                cursor.item().map(|item| item.buffer_id)
3428            } else {
3429                None
3430            }
3431        })
3432    }
3433
3434    pub fn excerpts(
3435        &self,
3436    ) -> impl Iterator<Item = (ExcerptId, &BufferSnapshot, ExcerptRange<text::Anchor>)> {
3437        self.excerpts
3438            .iter()
3439            .map(|excerpt| (excerpt.id, &excerpt.buffer, excerpt.range.clone()))
3440    }
3441
3442    pub fn all_excerpts(&self) -> impl Iterator<Item = MultiBufferExcerpt> {
3443        let mut cursor = self.excerpts.cursor::<(usize, Point)>(&());
3444        cursor.next(&());
3445        std::iter::from_fn(move || {
3446            let excerpt = cursor.item()?;
3447            let excerpt = MultiBufferExcerpt::new(excerpt, *cursor.start());
3448            cursor.next(&());
3449            Some(excerpt)
3450        })
3451    }
3452
3453    pub fn excerpts_for_range<T: ToOffset>(
3454        &self,
3455        range: Range<T>,
3456    ) -> impl Iterator<Item = MultiBufferExcerpt> + '_ {
3457        let range = range.start.to_offset(self)..range.end.to_offset(self);
3458
3459        let mut cursor = self.excerpts.cursor::<(usize, Point)>(&());
3460        cursor.seek(&range.start, Bias::Right, &());
3461        cursor.prev(&());
3462
3463        iter::from_fn(move || {
3464            cursor.next(&());
3465            if cursor.start().0 < range.end {
3466                cursor
3467                    .item()
3468                    .map(|item| MultiBufferExcerpt::new(item, *cursor.start()))
3469            } else {
3470                None
3471            }
3472        })
3473    }
3474
3475    pub fn excerpts_for_range_rev<T: ToOffset>(
3476        &self,
3477        range: Range<T>,
3478    ) -> impl Iterator<Item = MultiBufferExcerpt> + '_ {
3479        let range = range.start.to_offset(self)..range.end.to_offset(self);
3480
3481        let mut cursor = self.excerpts.cursor::<(usize, Point)>(&());
3482        cursor.seek(&range.end, Bias::Left, &());
3483        if cursor.item().is_none() {
3484            cursor.prev(&());
3485        }
3486
3487        std::iter::from_fn(move || {
3488            let excerpt = cursor.item()?;
3489            let excerpt = MultiBufferExcerpt::new(excerpt, *cursor.start());
3490            cursor.prev(&());
3491            Some(excerpt)
3492        })
3493    }
3494
3495    pub fn excerpt_before(&self, id: ExcerptId) -> Option<MultiBufferExcerpt<'_>> {
3496        let start_locator = self.excerpt_locator_for_id(id);
3497        let mut cursor = self.excerpts.cursor::<ExcerptSummary>(&());
3498        cursor.seek(start_locator, Bias::Left, &());
3499        cursor.prev(&());
3500        let excerpt = cursor.item()?;
3501        let excerpt_offset = cursor.start().text.len;
3502        let excerpt_position = cursor.start().text.lines;
3503        Some(MultiBufferExcerpt {
3504            excerpt,
3505            excerpt_offset,
3506            excerpt_position,
3507        })
3508    }
3509
3510    pub fn excerpt_after(&self, id: ExcerptId) -> Option<MultiBufferExcerpt<'_>> {
3511        let start_locator = self.excerpt_locator_for_id(id);
3512        let mut cursor = self.excerpts.cursor::<ExcerptSummary>(&());
3513        cursor.seek(start_locator, Bias::Left, &());
3514        cursor.next(&());
3515        let excerpt = cursor.item()?;
3516        let excerpt_offset = cursor.start().text.len;
3517        let excerpt_position = cursor.start().text.lines;
3518        Some(MultiBufferExcerpt {
3519            excerpt,
3520            excerpt_offset,
3521            excerpt_position,
3522        })
3523    }
3524
3525    pub fn excerpt_boundaries_in_range<R, T>(
3526        &self,
3527        range: R,
3528    ) -> impl Iterator<Item = ExcerptBoundary> + '_
3529    where
3530        R: RangeBounds<T>,
3531        T: ToOffset,
3532    {
3533        let start_offset;
3534        let start = match range.start_bound() {
3535            Bound::Included(start) => {
3536                start_offset = start.to_offset(self);
3537                Bound::Included(start_offset)
3538            }
3539            Bound::Excluded(start) => {
3540                start_offset = start.to_offset(self);
3541                Bound::Excluded(start_offset)
3542            }
3543            Bound::Unbounded => {
3544                start_offset = 0;
3545                Bound::Unbounded
3546            }
3547        };
3548        let end = match range.end_bound() {
3549            Bound::Included(end) => Bound::Included(end.to_offset(self)),
3550            Bound::Excluded(end) => Bound::Excluded(end.to_offset(self)),
3551            Bound::Unbounded => Bound::Unbounded,
3552        };
3553        let bounds = (start, end);
3554
3555        let mut cursor = self.excerpts.cursor::<(usize, Point)>(&());
3556        cursor.seek(&start_offset, Bias::Right, &());
3557        if cursor.item().is_none() {
3558            cursor.prev(&());
3559        }
3560        if !bounds.contains(&cursor.start().0) {
3561            cursor.next(&());
3562        }
3563
3564        let mut visited_end = false;
3565        std::iter::from_fn(move || {
3566            if self.singleton {
3567                None
3568            } else if bounds.contains(&cursor.start().0) {
3569                let next = cursor.item().map(|excerpt| ExcerptInfo {
3570                    id: excerpt.id,
3571                    buffer: excerpt.buffer.clone(),
3572                    buffer_id: excerpt.buffer_id,
3573                    range: excerpt.range.clone(),
3574                    text_summary: excerpt.text_summary.clone(),
3575                });
3576
3577                if next.is_none() {
3578                    if visited_end {
3579                        return None;
3580                    } else {
3581                        visited_end = true;
3582                    }
3583                }
3584
3585                let prev = cursor.prev_item().map(|prev_excerpt| ExcerptInfo {
3586                    id: prev_excerpt.id,
3587                    buffer: prev_excerpt.buffer.clone(),
3588                    buffer_id: prev_excerpt.buffer_id,
3589                    range: prev_excerpt.range.clone(),
3590                    text_summary: prev_excerpt.text_summary.clone(),
3591                });
3592                let row = MultiBufferRow(cursor.start().1.row);
3593
3594                cursor.next(&());
3595
3596                Some(ExcerptBoundary { row, prev, next })
3597            } else {
3598                None
3599            }
3600        })
3601    }
3602
3603    pub fn edit_count(&self) -> usize {
3604        self.edit_count
3605    }
3606
3607    pub fn non_text_state_update_count(&self) -> usize {
3608        self.non_text_state_update_count
3609    }
3610
3611    /// Returns the smallest enclosing bracket ranges containing the given range or
3612    /// None if no brackets contain range or the range is not contained in a single
3613    /// excerpt
3614    ///
3615    /// Can optionally pass a range_filter to filter the ranges of brackets to consider
3616    pub fn innermost_enclosing_bracket_ranges<T: ToOffset>(
3617        &self,
3618        range: Range<T>,
3619        range_filter: Option<&dyn Fn(Range<usize>, Range<usize>) -> bool>,
3620    ) -> Option<(Range<usize>, Range<usize>)> {
3621        let range = range.start.to_offset(self)..range.end.to_offset(self);
3622        let excerpt = self.excerpt_containing(range.clone())?;
3623
3624        // Filter to ranges contained in the excerpt
3625        let range_filter = |open: Range<usize>, close: Range<usize>| -> bool {
3626            excerpt.contains_buffer_range(open.start..close.end)
3627                && range_filter.map_or(true, |filter| {
3628                    filter(
3629                        excerpt.map_range_from_buffer(open),
3630                        excerpt.map_range_from_buffer(close),
3631                    )
3632                })
3633        };
3634
3635        let (open, close) = excerpt.buffer().innermost_enclosing_bracket_ranges(
3636            excerpt.map_range_to_buffer(range),
3637            Some(&range_filter),
3638        )?;
3639
3640        Some((
3641            excerpt.map_range_from_buffer(open),
3642            excerpt.map_range_from_buffer(close),
3643        ))
3644    }
3645
3646    /// Returns enclosing bracket ranges containing the given range or returns None if the range is
3647    /// not contained in a single excerpt
3648    pub fn enclosing_bracket_ranges<T: ToOffset>(
3649        &self,
3650        range: Range<T>,
3651    ) -> Option<impl Iterator<Item = (Range<usize>, Range<usize>)> + '_> {
3652        let range = range.start.to_offset(self)..range.end.to_offset(self);
3653        let excerpt = self.excerpt_containing(range.clone())?;
3654
3655        Some(
3656            excerpt
3657                .buffer()
3658                .enclosing_bracket_ranges(excerpt.map_range_to_buffer(range))
3659                .filter_map(move |(open, close)| {
3660                    if excerpt.contains_buffer_range(open.start..close.end) {
3661                        Some((
3662                            excerpt.map_range_from_buffer(open),
3663                            excerpt.map_range_from_buffer(close),
3664                        ))
3665                    } else {
3666                        None
3667                    }
3668                }),
3669        )
3670    }
3671
3672    /// Returns bracket range pairs overlapping the given `range` or returns None if the `range` is
3673    /// not contained in a single excerpt
3674    pub fn bracket_ranges<T: ToOffset>(
3675        &self,
3676        range: Range<T>,
3677    ) -> Option<impl Iterator<Item = (Range<usize>, Range<usize>)> + '_> {
3678        let range = range.start.to_offset(self)..range.end.to_offset(self);
3679        let excerpt = self.excerpt_containing(range.clone())?;
3680
3681        Some(
3682            excerpt
3683                .buffer()
3684                .bracket_ranges(excerpt.map_range_to_buffer(range))
3685                .filter_map(move |(start_bracket_range, close_bracket_range)| {
3686                    let buffer_range = start_bracket_range.start..close_bracket_range.end;
3687                    if excerpt.contains_buffer_range(buffer_range) {
3688                        Some((
3689                            excerpt.map_range_from_buffer(start_bracket_range),
3690                            excerpt.map_range_from_buffer(close_bracket_range),
3691                        ))
3692                    } else {
3693                        None
3694                    }
3695                }),
3696        )
3697    }
3698
3699    pub fn redacted_ranges<'a, T: ToOffset>(
3700        &'a self,
3701        range: Range<T>,
3702        redaction_enabled: impl Fn(Option<&Arc<dyn File>>) -> bool + 'a,
3703    ) -> impl Iterator<Item = Range<usize>> + 'a {
3704        let range = range.start.to_offset(self)..range.end.to_offset(self);
3705        self.excerpts_for_range(range.clone())
3706            .filter(move |excerpt| redaction_enabled(excerpt.buffer().file()))
3707            .flat_map(move |excerpt| {
3708                excerpt
3709                    .buffer()
3710                    .redacted_ranges(excerpt.buffer_range().clone())
3711                    .map(move |redacted_range| excerpt.map_range_from_buffer(redacted_range))
3712                    .skip_while(move |redacted_range| redacted_range.end < range.start)
3713                    .take_while(move |redacted_range| redacted_range.start < range.end)
3714            })
3715    }
3716
3717    pub fn runnable_ranges(
3718        &self,
3719        range: Range<Anchor>,
3720    ) -> impl Iterator<Item = language::RunnableRange> + '_ {
3721        let range = range.start.to_offset(self)..range.end.to_offset(self);
3722        self.excerpts_for_range(range.clone())
3723            .flat_map(move |excerpt| {
3724                let excerpt_buffer_start =
3725                    excerpt.buffer_range().start.to_offset(&excerpt.buffer());
3726
3727                excerpt
3728                    .buffer()
3729                    .runnable_ranges(excerpt.buffer_range())
3730                    .filter_map(move |mut runnable| {
3731                        // Re-base onto the excerpts coordinates in the multibuffer
3732                        //
3733                        // The node matching our runnables query might partially overlap with
3734                        // the provided range. If the run indicator is outside of excerpt bounds, do not actually show it.
3735                        if runnable.run_range.start < excerpt_buffer_start {
3736                            return None;
3737                        }
3738                        if language::ToPoint::to_point(&runnable.run_range.end, &excerpt.buffer())
3739                            .row
3740                            > excerpt.max_buffer_row()
3741                        {
3742                            return None;
3743                        }
3744                        runnable.run_range = excerpt.map_range_from_buffer(runnable.run_range);
3745
3746                        Some(runnable)
3747                    })
3748                    .skip_while(move |runnable| runnable.run_range.end < range.start)
3749                    .take_while(move |runnable| runnable.run_range.start < range.end)
3750            })
3751    }
3752
3753    pub fn indent_guides_in_range(
3754        &self,
3755        range: Range<Anchor>,
3756        ignore_disabled_for_language: bool,
3757        cx: &AppContext,
3758    ) -> Vec<MultiBufferIndentGuide> {
3759        // Fast path for singleton buffers, we can skip the conversion between offsets.
3760        if let Some((_, _, snapshot)) = self.as_singleton() {
3761            return snapshot
3762                .indent_guides_in_range(
3763                    range.start.text_anchor..range.end.text_anchor,
3764                    ignore_disabled_for_language,
3765                    cx,
3766                )
3767                .into_iter()
3768                .map(|guide| MultiBufferIndentGuide {
3769                    multibuffer_row_range: MultiBufferRow(guide.start_row)
3770                        ..MultiBufferRow(guide.end_row),
3771                    buffer: guide,
3772                })
3773                .collect();
3774        }
3775
3776        let range = range.start.to_offset(self)..range.end.to_offset(self);
3777
3778        self.excerpts_for_range(range.clone())
3779            .flat_map(move |excerpt| {
3780                let excerpt_buffer_start_row =
3781                    excerpt.buffer_range().start.to_point(&excerpt.buffer()).row;
3782                let excerpt_offset_row = excerpt.start_point().row;
3783
3784                excerpt
3785                    .buffer()
3786                    .indent_guides_in_range(
3787                        excerpt.buffer_range(),
3788                        ignore_disabled_for_language,
3789                        cx,
3790                    )
3791                    .into_iter()
3792                    .map(move |indent_guide| {
3793                        let start_row = excerpt_offset_row
3794                            + (indent_guide.start_row - excerpt_buffer_start_row);
3795                        let end_row =
3796                            excerpt_offset_row + (indent_guide.end_row - excerpt_buffer_start_row);
3797
3798                        MultiBufferIndentGuide {
3799                            multibuffer_row_range: MultiBufferRow(start_row)
3800                                ..MultiBufferRow(end_row),
3801                            buffer: indent_guide,
3802                        }
3803                    })
3804            })
3805            .collect()
3806    }
3807
3808    pub fn trailing_excerpt_update_count(&self) -> usize {
3809        self.trailing_excerpt_update_count
3810    }
3811
3812    pub fn file_at<T: ToOffset>(&self, point: T) -> Option<&Arc<dyn File>> {
3813        self.point_to_buffer_offset(point)
3814            .and_then(|(buffer, _)| buffer.file())
3815    }
3816
3817    pub fn language_at<T: ToOffset>(&self, point: T) -> Option<&Arc<Language>> {
3818        self.point_to_buffer_offset(point)
3819            .and_then(|(buffer, offset)| buffer.language_at(offset))
3820    }
3821
3822    pub fn settings_at<'a, T: ToOffset>(
3823        &'a self,
3824        point: T,
3825        cx: &'a AppContext,
3826    ) -> Cow<'a, LanguageSettings> {
3827        let mut language = None;
3828        let mut file = None;
3829        if let Some((buffer, offset)) = self.point_to_buffer_offset(point) {
3830            language = buffer.language_at(offset);
3831            file = buffer.file();
3832        }
3833        language_settings(language.map(|l| l.name()), file, cx)
3834    }
3835
3836    pub fn language_scope_at<T: ToOffset>(&self, point: T) -> Option<LanguageScope> {
3837        self.point_to_buffer_offset(point)
3838            .and_then(|(buffer, offset)| buffer.language_scope_at(offset))
3839    }
3840
3841    pub fn char_classifier_at<T: ToOffset>(&self, point: T) -> CharClassifier {
3842        self.point_to_buffer_offset(point)
3843            .map(|(buffer, offset)| buffer.char_classifier_at(offset))
3844            .unwrap_or_default()
3845    }
3846
3847    pub fn language_indent_size_at<T: ToOffset>(
3848        &self,
3849        position: T,
3850        cx: &AppContext,
3851    ) -> Option<IndentSize> {
3852        let (buffer_snapshot, offset) = self.point_to_buffer_offset(position)?;
3853        Some(buffer_snapshot.language_indent_size_at(offset, cx))
3854    }
3855
3856    pub fn is_dirty(&self) -> bool {
3857        self.is_dirty
3858    }
3859
3860    pub fn has_deleted_file(&self) -> bool {
3861        self.has_deleted_file
3862    }
3863
3864    pub fn has_conflict(&self) -> bool {
3865        self.has_conflict
3866    }
3867
3868    pub fn has_diagnostics(&self) -> bool {
3869        self.excerpts
3870            .iter()
3871            .any(|excerpt| excerpt.buffer.has_diagnostics())
3872    }
3873
3874    pub fn diagnostic_group(
3875        &self,
3876        group_id: usize,
3877    ) -> impl Iterator<Item = DiagnosticEntry<Anchor>> + '_ {
3878        self.all_excerpts().flat_map(move |excerpt| {
3879            excerpt.buffer().diagnostic_group(group_id).map(
3880                move |DiagnosticEntry { diagnostic, range }| DiagnosticEntry {
3881                    diagnostic,
3882                    range: self.anchor_in_excerpt(excerpt.id(), range.start).unwrap()
3883                        ..self.anchor_in_excerpt(excerpt.id(), range.end).unwrap(),
3884                },
3885            )
3886        })
3887    }
3888
3889    pub fn diagnostics_in_range<'a, T>(
3890        &'a self,
3891        range: Range<T>,
3892        reversed: bool,
3893    ) -> impl Iterator<Item = DiagnosticEntry<Anchor>> + 'a
3894    where
3895        T: 'a + ToOffset,
3896    {
3897        let mut ranges = self.range_to_buffer_ranges(range);
3898        if reversed {
3899            ranges.reverse();
3900        }
3901        ranges.into_iter().flat_map(move |(excerpt, range)| {
3902            let excerpt_id = excerpt.id();
3903            excerpt.buffer().diagnostics_in_range(range, reversed).map(
3904                move |DiagnosticEntry { diagnostic, range }| DiagnosticEntry {
3905                    diagnostic,
3906                    range: self.anchor_in_excerpt(excerpt_id, range.start).unwrap()
3907                        ..self.anchor_in_excerpt(excerpt_id, range.end).unwrap(),
3908                },
3909            )
3910        })
3911    }
3912
3913    pub fn syntax_ancestor<T: ToOffset>(
3914        &self,
3915        range: Range<T>,
3916    ) -> Option<(tree_sitter::Node, Range<usize>)> {
3917        let range = range.start.to_offset(self)..range.end.to_offset(self);
3918        let excerpt = self.excerpt_containing(range.clone())?;
3919        let node = excerpt
3920            .buffer()
3921            .syntax_ancestor(excerpt.map_range_to_buffer(range))?;
3922        Some((node, excerpt.map_range_from_buffer(node.byte_range())))
3923    }
3924
3925    pub fn outline(&self, theme: Option<&SyntaxTheme>) -> Option<Outline<Anchor>> {
3926        let (excerpt_id, _, buffer) = self.as_singleton()?;
3927        let outline = buffer.outline(theme)?;
3928        Some(Outline::new(
3929            outline
3930                .items
3931                .into_iter()
3932                .flat_map(|item| {
3933                    Some(OutlineItem {
3934                        depth: item.depth,
3935                        range: self.anchor_in_excerpt(*excerpt_id, item.range.start)?
3936                            ..self.anchor_in_excerpt(*excerpt_id, item.range.end)?,
3937                        text: item.text,
3938                        highlight_ranges: item.highlight_ranges,
3939                        name_ranges: item.name_ranges,
3940                        body_range: item.body_range.and_then(|body_range| {
3941                            Some(
3942                                self.anchor_in_excerpt(*excerpt_id, body_range.start)?
3943                                    ..self.anchor_in_excerpt(*excerpt_id, body_range.end)?,
3944                            )
3945                        }),
3946                        annotation_range: item.annotation_range.and_then(|annotation_range| {
3947                            Some(
3948                                self.anchor_in_excerpt(*excerpt_id, annotation_range.start)?
3949                                    ..self.anchor_in_excerpt(*excerpt_id, annotation_range.end)?,
3950                            )
3951                        }),
3952                    })
3953                })
3954                .collect(),
3955        ))
3956    }
3957
3958    pub fn symbols_containing<T: ToOffset>(
3959        &self,
3960        offset: T,
3961        theme: Option<&SyntaxTheme>,
3962    ) -> Option<(BufferId, Vec<OutlineItem<Anchor>>)> {
3963        let anchor = self.anchor_before(offset);
3964        let excerpt_id = anchor.excerpt_id;
3965        let excerpt = self.excerpt(excerpt_id)?;
3966        Some((
3967            excerpt.buffer_id,
3968            excerpt
3969                .buffer
3970                .symbols_containing(anchor.text_anchor, theme)
3971                .into_iter()
3972                .flatten()
3973                .flat_map(|item| {
3974                    Some(OutlineItem {
3975                        depth: item.depth,
3976                        range: self.anchor_in_excerpt(excerpt_id, item.range.start)?
3977                            ..self.anchor_in_excerpt(excerpt_id, item.range.end)?,
3978                        text: item.text,
3979                        highlight_ranges: item.highlight_ranges,
3980                        name_ranges: item.name_ranges,
3981                        body_range: item.body_range.and_then(|body_range| {
3982                            Some(
3983                                self.anchor_in_excerpt(excerpt_id, body_range.start)?
3984                                    ..self.anchor_in_excerpt(excerpt_id, body_range.end)?,
3985                            )
3986                        }),
3987                        annotation_range: item.annotation_range.and_then(|body_range| {
3988                            Some(
3989                                self.anchor_in_excerpt(excerpt_id, body_range.start)?
3990                                    ..self.anchor_in_excerpt(excerpt_id, body_range.end)?,
3991                            )
3992                        }),
3993                    })
3994                })
3995                .collect(),
3996        ))
3997    }
3998
3999    fn excerpt_locator_for_id(&self, id: ExcerptId) -> &Locator {
4000        if id == ExcerptId::min() {
4001            Locator::min_ref()
4002        } else if id == ExcerptId::max() {
4003            Locator::max_ref()
4004        } else {
4005            let mut cursor = self.excerpt_ids.cursor::<ExcerptId>(&());
4006            cursor.seek(&id, Bias::Left, &());
4007            if let Some(entry) = cursor.item() {
4008                if entry.id == id {
4009                    return &entry.locator;
4010                }
4011            }
4012            panic!("invalid excerpt id {:?}", id)
4013        }
4014    }
4015
4016    /// Returns the locators referenced by the given excerpt IDs, sorted by locator.
4017    fn excerpt_locators_for_ids(
4018        &self,
4019        ids: impl IntoIterator<Item = ExcerptId>,
4020    ) -> SmallVec<[Locator; 1]> {
4021        let mut sorted_ids = ids.into_iter().collect::<SmallVec<[_; 1]>>();
4022        sorted_ids.sort_unstable();
4023        let mut locators = SmallVec::new();
4024
4025        while sorted_ids.last() == Some(&ExcerptId::max()) {
4026            sorted_ids.pop();
4027            if let Some(mapping) = self.excerpt_ids.last() {
4028                locators.push(mapping.locator.clone());
4029            }
4030        }
4031
4032        let mut sorted_ids = sorted_ids.into_iter().dedup().peekable();
4033        if sorted_ids.peek() == Some(&ExcerptId::min()) {
4034            sorted_ids.next();
4035            if let Some(mapping) = self.excerpt_ids.first() {
4036                locators.push(mapping.locator.clone());
4037            }
4038        }
4039
4040        let mut cursor = self.excerpt_ids.cursor::<ExcerptId>(&());
4041        for id in sorted_ids {
4042            if cursor.seek_forward(&id, Bias::Left, &()) {
4043                locators.push(cursor.item().unwrap().locator.clone());
4044            } else {
4045                panic!("invalid excerpt id {:?}", id);
4046            }
4047        }
4048
4049        locators.sort_unstable();
4050        locators
4051    }
4052
4053    pub fn buffer_id_for_excerpt(&self, excerpt_id: ExcerptId) -> Option<BufferId> {
4054        Some(self.excerpt(excerpt_id)?.buffer_id)
4055    }
4056
4057    pub fn buffer_for_excerpt(&self, excerpt_id: ExcerptId) -> Option<&BufferSnapshot> {
4058        Some(&self.excerpt(excerpt_id)?.buffer)
4059    }
4060
4061    pub fn range_for_excerpt<'a, T: sum_tree::Dimension<'a, ExcerptSummary>>(
4062        &'a self,
4063        excerpt_id: ExcerptId,
4064    ) -> Option<Range<T>> {
4065        let mut cursor = self.excerpts.cursor::<(Option<&Locator>, T)>(&());
4066        let locator = self.excerpt_locator_for_id(excerpt_id);
4067        if cursor.seek(&Some(locator), Bias::Left, &()) {
4068            let start = cursor.start().1.clone();
4069            let end = cursor.end(&()).1;
4070            Some(start..end)
4071        } else {
4072            None
4073        }
4074    }
4075
4076    fn excerpt(&self, excerpt_id: ExcerptId) -> Option<&Excerpt> {
4077        let mut cursor = self.excerpts.cursor::<Option<&Locator>>(&());
4078        let locator = self.excerpt_locator_for_id(excerpt_id);
4079        cursor.seek(&Some(locator), Bias::Left, &());
4080        if let Some(excerpt) = cursor.item() {
4081            if excerpt.id == excerpt_id {
4082                return Some(excerpt);
4083            }
4084        }
4085        None
4086    }
4087
4088    /// Returns the excerpt containing range and its offset start within the multibuffer or none if `range` spans multiple excerpts
4089    pub fn excerpt_containing<T: ToOffset>(&self, range: Range<T>) -> Option<MultiBufferExcerpt> {
4090        let range = range.start.to_offset(self)..range.end.to_offset(self);
4091
4092        let mut cursor = self.excerpts.cursor::<(usize, Point)>(&());
4093        cursor.seek(&range.start, Bias::Right, &());
4094        let start_excerpt = cursor.item()?;
4095
4096        if range.start == range.end {
4097            return Some(MultiBufferExcerpt::new(start_excerpt, *cursor.start()));
4098        }
4099
4100        cursor.seek(&range.end, Bias::Right, &());
4101        let end_excerpt = cursor.item()?;
4102
4103        if start_excerpt.id == end_excerpt.id {
4104            Some(MultiBufferExcerpt::new(start_excerpt, *cursor.start()))
4105        } else {
4106            None
4107        }
4108    }
4109
4110    // Takes an iterator over anchor ranges and returns a new iterator over anchor ranges that don't
4111    // span across excerpt boundaries.
4112    pub fn split_ranges<'a, I>(&'a self, ranges: I) -> impl Iterator<Item = Range<Anchor>> + 'a
4113    where
4114        I: IntoIterator<Item = Range<Anchor>> + 'a,
4115    {
4116        let mut ranges = ranges.into_iter().map(|range| range.to_offset(self));
4117        let mut cursor = self.excerpts.cursor::<(usize, Point)>(&());
4118        cursor.next(&());
4119        let mut current_range = ranges.next();
4120        iter::from_fn(move || {
4121            let range = current_range.clone()?;
4122            if range.start >= cursor.end(&()).0 {
4123                cursor.seek_forward(&range.start, Bias::Right, &());
4124                if range.start == self.len() {
4125                    cursor.prev(&());
4126                }
4127            }
4128
4129            let excerpt = cursor.item()?;
4130            let range_start_in_excerpt = cmp::max(range.start, cursor.start().0);
4131            let range_end_in_excerpt = if excerpt.has_trailing_newline {
4132                cmp::min(range.end, cursor.end(&()).0 - 1)
4133            } else {
4134                cmp::min(range.end, cursor.end(&()).0)
4135            };
4136            let buffer_range = MultiBufferExcerpt::new(excerpt, *cursor.start())
4137                .map_range_to_buffer(range_start_in_excerpt..range_end_in_excerpt);
4138
4139            let subrange_start_anchor = Anchor {
4140                buffer_id: Some(excerpt.buffer_id),
4141                excerpt_id: excerpt.id,
4142                text_anchor: excerpt.buffer.anchor_before(buffer_range.start),
4143            };
4144            let subrange_end_anchor = Anchor {
4145                buffer_id: Some(excerpt.buffer_id),
4146                excerpt_id: excerpt.id,
4147                text_anchor: excerpt.buffer.anchor_after(buffer_range.end),
4148            };
4149
4150            if range.end > cursor.end(&()).0 {
4151                cursor.next(&());
4152            } else {
4153                current_range = ranges.next();
4154            }
4155
4156            Some(subrange_start_anchor..subrange_end_anchor)
4157        })
4158    }
4159
4160    pub fn range_to_buffer_ranges<T: ToOffset>(
4161        &self,
4162        range: Range<T>,
4163    ) -> Vec<(MultiBufferExcerpt<'_>, Range<usize>)> {
4164        let start = range.start.to_offset(self);
4165        let end = range.end.to_offset(self);
4166
4167        let mut result = Vec::new();
4168        let mut cursor = self.excerpts.cursor::<(usize, Point)>(&());
4169        cursor.seek(&start, Bias::Right, &());
4170        if cursor.item().is_none() {
4171            cursor.prev(&());
4172        }
4173
4174        while let Some(excerpt) = cursor.item() {
4175            if cursor.start().0 > end {
4176                break;
4177            }
4178
4179            let mut end_before_newline = cursor.end(&()).0;
4180            if excerpt.has_trailing_newline {
4181                end_before_newline -= 1;
4182            }
4183            let excerpt_start = excerpt.range.context.start.to_offset(&excerpt.buffer);
4184            let start = excerpt_start + (cmp::max(start, cursor.start().0) - cursor.start().0);
4185            let end = excerpt_start + (cmp::min(end, end_before_newline) - cursor.start().0);
4186            result.push((
4187                MultiBufferExcerpt::new(&excerpt, *cursor.start()),
4188                start..end,
4189            ));
4190            cursor.next(&());
4191        }
4192
4193        result
4194    }
4195
4196    /// Returns excerpts overlapping the given ranges. If range spans multiple excerpts returns one range for each excerpt
4197    ///
4198    /// The ranges are specified in the coordinate space of the multibuffer, not the individual excerpted buffers.
4199    /// Each returned excerpt's range is in the coordinate space of its source buffer.
4200    pub fn excerpts_in_ranges(
4201        &self,
4202        ranges: impl IntoIterator<Item = Range<Anchor>>,
4203    ) -> impl Iterator<Item = (ExcerptId, &BufferSnapshot, Range<usize>)> {
4204        let mut ranges = ranges.into_iter().map(|range| range.to_offset(self));
4205        let mut cursor = self.excerpts.cursor::<(usize, Point)>(&());
4206        cursor.next(&());
4207        let mut current_range = ranges.next();
4208        iter::from_fn(move || {
4209            let range = current_range.clone()?;
4210            if range.start >= cursor.end(&()).0 {
4211                cursor.seek_forward(&range.start, Bias::Right, &());
4212                if range.start == self.len() {
4213                    cursor.prev(&());
4214                }
4215            }
4216
4217            let excerpt = cursor.item()?;
4218            let range_start_in_excerpt = cmp::max(range.start, cursor.start().0);
4219            let range_end_in_excerpt = if excerpt.has_trailing_newline {
4220                cmp::min(range.end, cursor.end(&()).0 - 1)
4221            } else {
4222                cmp::min(range.end, cursor.end(&()).0)
4223            };
4224            let buffer_range = MultiBufferExcerpt::new(excerpt, *cursor.start())
4225                .map_range_to_buffer(range_start_in_excerpt..range_end_in_excerpt);
4226
4227            if range.end > cursor.end(&()).0 {
4228                cursor.next(&());
4229            } else {
4230                current_range = ranges.next();
4231            }
4232
4233            Some((excerpt.id, &excerpt.buffer, buffer_range))
4234        })
4235    }
4236
4237    pub fn selections_in_range<'a>(
4238        &'a self,
4239        range: &'a Range<Anchor>,
4240        include_local: bool,
4241    ) -> impl 'a + Iterator<Item = (ReplicaId, bool, CursorShape, Selection<Anchor>)> {
4242        let mut cursor = self.excerpts.cursor::<ExcerptSummary>(&());
4243        let start_locator = self.excerpt_locator_for_id(range.start.excerpt_id);
4244        let end_locator = self.excerpt_locator_for_id(range.end.excerpt_id);
4245        cursor.seek(start_locator, Bias::Left, &());
4246        cursor
4247            .take_while(move |excerpt| excerpt.locator <= *end_locator)
4248            .flat_map(move |excerpt| {
4249                let mut query_range = excerpt.range.context.start..excerpt.range.context.end;
4250                if excerpt.id == range.start.excerpt_id {
4251                    query_range.start = range.start.text_anchor;
4252                }
4253                if excerpt.id == range.end.excerpt_id {
4254                    query_range.end = range.end.text_anchor;
4255                }
4256
4257                excerpt
4258                    .buffer
4259                    .selections_in_range(query_range, include_local)
4260                    .flat_map(move |(replica_id, line_mode, cursor_shape, selections)| {
4261                        selections.map(move |selection| {
4262                            let mut start = Anchor {
4263                                buffer_id: Some(excerpt.buffer_id),
4264                                excerpt_id: excerpt.id,
4265                                text_anchor: selection.start,
4266                            };
4267                            let mut end = Anchor {
4268                                buffer_id: Some(excerpt.buffer_id),
4269                                excerpt_id: excerpt.id,
4270                                text_anchor: selection.end,
4271                            };
4272                            if range.start.cmp(&start, self).is_gt() {
4273                                start = range.start;
4274                            }
4275                            if range.end.cmp(&end, self).is_lt() {
4276                                end = range.end;
4277                            }
4278
4279                            (
4280                                replica_id,
4281                                line_mode,
4282                                cursor_shape,
4283                                Selection {
4284                                    id: selection.id,
4285                                    start,
4286                                    end,
4287                                    reversed: selection.reversed,
4288                                    goal: selection.goal,
4289                                },
4290                            )
4291                        })
4292                    })
4293            })
4294    }
4295
4296    pub fn show_headers(&self) -> bool {
4297        self.show_headers
4298    }
4299}
4300
4301#[cfg(any(test, feature = "test-support"))]
4302impl MultiBufferSnapshot {
4303    pub fn random_byte_range(&self, start_offset: usize, rng: &mut impl rand::Rng) -> Range<usize> {
4304        let end = self.clip_offset(rng.gen_range(start_offset..=self.len()), Bias::Right);
4305        let start = self.clip_offset(rng.gen_range(start_offset..=end), Bias::Right);
4306        start..end
4307    }
4308}
4309
4310impl History {
4311    fn start_transaction(&mut self, now: Instant) -> Option<TransactionId> {
4312        self.transaction_depth += 1;
4313        if self.transaction_depth == 1 {
4314            let id = self.next_transaction_id.tick();
4315            self.undo_stack.push(Transaction {
4316                id,
4317                buffer_transactions: Default::default(),
4318                first_edit_at: now,
4319                last_edit_at: now,
4320                suppress_grouping: false,
4321            });
4322            Some(id)
4323        } else {
4324            None
4325        }
4326    }
4327
4328    fn end_transaction(
4329        &mut self,
4330        now: Instant,
4331        buffer_transactions: HashMap<BufferId, TransactionId>,
4332    ) -> bool {
4333        assert_ne!(self.transaction_depth, 0);
4334        self.transaction_depth -= 1;
4335        if self.transaction_depth == 0 {
4336            if buffer_transactions.is_empty() {
4337                self.undo_stack.pop();
4338                false
4339            } else {
4340                self.redo_stack.clear();
4341                let transaction = self.undo_stack.last_mut().unwrap();
4342                transaction.last_edit_at = now;
4343                for (buffer_id, transaction_id) in buffer_transactions {
4344                    transaction
4345                        .buffer_transactions
4346                        .entry(buffer_id)
4347                        .or_insert(transaction_id);
4348                }
4349                true
4350            }
4351        } else {
4352            false
4353        }
4354    }
4355
4356    fn push_transaction<'a, T>(
4357        &mut self,
4358        buffer_transactions: T,
4359        now: Instant,
4360        cx: &ModelContext<MultiBuffer>,
4361    ) where
4362        T: IntoIterator<Item = (&'a Model<Buffer>, &'a language::Transaction)>,
4363    {
4364        assert_eq!(self.transaction_depth, 0);
4365        let transaction = Transaction {
4366            id: self.next_transaction_id.tick(),
4367            buffer_transactions: buffer_transactions
4368                .into_iter()
4369                .map(|(buffer, transaction)| (buffer.read(cx).remote_id(), transaction.id))
4370                .collect(),
4371            first_edit_at: now,
4372            last_edit_at: now,
4373            suppress_grouping: false,
4374        };
4375        if !transaction.buffer_transactions.is_empty() {
4376            self.undo_stack.push(transaction);
4377            self.redo_stack.clear();
4378        }
4379    }
4380
4381    fn finalize_last_transaction(&mut self) {
4382        if let Some(transaction) = self.undo_stack.last_mut() {
4383            transaction.suppress_grouping = true;
4384        }
4385    }
4386
4387    fn forget(&mut self, transaction_id: TransactionId) -> Option<Transaction> {
4388        if let Some(ix) = self
4389            .undo_stack
4390            .iter()
4391            .rposition(|transaction| transaction.id == transaction_id)
4392        {
4393            Some(self.undo_stack.remove(ix))
4394        } else if let Some(ix) = self
4395            .redo_stack
4396            .iter()
4397            .rposition(|transaction| transaction.id == transaction_id)
4398        {
4399            Some(self.redo_stack.remove(ix))
4400        } else {
4401            None
4402        }
4403    }
4404
4405    fn transaction(&self, transaction_id: TransactionId) -> Option<&Transaction> {
4406        self.undo_stack
4407            .iter()
4408            .find(|transaction| transaction.id == transaction_id)
4409            .or_else(|| {
4410                self.redo_stack
4411                    .iter()
4412                    .find(|transaction| transaction.id == transaction_id)
4413            })
4414    }
4415
4416    fn transaction_mut(&mut self, transaction_id: TransactionId) -> Option<&mut Transaction> {
4417        self.undo_stack
4418            .iter_mut()
4419            .find(|transaction| transaction.id == transaction_id)
4420            .or_else(|| {
4421                self.redo_stack
4422                    .iter_mut()
4423                    .find(|transaction| transaction.id == transaction_id)
4424            })
4425    }
4426
4427    fn pop_undo(&mut self) -> Option<&mut Transaction> {
4428        assert_eq!(self.transaction_depth, 0);
4429        if let Some(transaction) = self.undo_stack.pop() {
4430            self.redo_stack.push(transaction);
4431            self.redo_stack.last_mut()
4432        } else {
4433            None
4434        }
4435    }
4436
4437    fn pop_redo(&mut self) -> Option<&mut Transaction> {
4438        assert_eq!(self.transaction_depth, 0);
4439        if let Some(transaction) = self.redo_stack.pop() {
4440            self.undo_stack.push(transaction);
4441            self.undo_stack.last_mut()
4442        } else {
4443            None
4444        }
4445    }
4446
4447    fn remove_from_undo(&mut self, transaction_id: TransactionId) -> Option<&Transaction> {
4448        let ix = self
4449            .undo_stack
4450            .iter()
4451            .rposition(|transaction| transaction.id == transaction_id)?;
4452        let transaction = self.undo_stack.remove(ix);
4453        self.redo_stack.push(transaction);
4454        self.redo_stack.last()
4455    }
4456
4457    fn group(&mut self) -> Option<TransactionId> {
4458        let mut count = 0;
4459        let mut transactions = self.undo_stack.iter();
4460        if let Some(mut transaction) = transactions.next_back() {
4461            while let Some(prev_transaction) = transactions.next_back() {
4462                if !prev_transaction.suppress_grouping
4463                    && transaction.first_edit_at - prev_transaction.last_edit_at
4464                        <= self.group_interval
4465                {
4466                    transaction = prev_transaction;
4467                    count += 1;
4468                } else {
4469                    break;
4470                }
4471            }
4472        }
4473        self.group_trailing(count)
4474    }
4475
4476    fn group_until(&mut self, transaction_id: TransactionId) {
4477        let mut count = 0;
4478        for transaction in self.undo_stack.iter().rev() {
4479            if transaction.id == transaction_id {
4480                self.group_trailing(count);
4481                break;
4482            } else if transaction.suppress_grouping {
4483                break;
4484            } else {
4485                count += 1;
4486            }
4487        }
4488    }
4489
4490    fn group_trailing(&mut self, n: usize) -> Option<TransactionId> {
4491        let new_len = self.undo_stack.len() - n;
4492        let (transactions_to_keep, transactions_to_merge) = self.undo_stack.split_at_mut(new_len);
4493        if let Some(last_transaction) = transactions_to_keep.last_mut() {
4494            if let Some(transaction) = transactions_to_merge.last() {
4495                last_transaction.last_edit_at = transaction.last_edit_at;
4496            }
4497            for to_merge in transactions_to_merge {
4498                for (buffer_id, transaction_id) in &to_merge.buffer_transactions {
4499                    last_transaction
4500                        .buffer_transactions
4501                        .entry(*buffer_id)
4502                        .or_insert(*transaction_id);
4503                }
4504            }
4505        }
4506
4507        self.undo_stack.truncate(new_len);
4508        self.undo_stack.last().map(|t| t.id)
4509    }
4510}
4511
4512impl Excerpt {
4513    fn new(
4514        id: ExcerptId,
4515        locator: Locator,
4516        buffer_id: BufferId,
4517        buffer: BufferSnapshot,
4518        range: ExcerptRange<text::Anchor>,
4519        has_trailing_newline: bool,
4520    ) -> Self {
4521        Excerpt {
4522            id,
4523            locator,
4524            max_buffer_row: range.context.end.to_point(&buffer).row,
4525            text_summary: buffer
4526                .text_summary_for_range::<TextSummary, _>(range.context.to_offset(&buffer)),
4527            buffer_id,
4528            buffer,
4529            range,
4530            has_trailing_newline,
4531        }
4532    }
4533
4534    fn chunks_in_range(&self, range: Range<usize>, language_aware: bool) -> ExcerptChunks {
4535        let content_start = self.range.context.start.to_offset(&self.buffer);
4536        let chunks_start = content_start + range.start;
4537        let chunks_end = content_start + cmp::min(range.end, self.text_summary.len);
4538
4539        let footer_height = if self.has_trailing_newline
4540            && range.start <= self.text_summary.len
4541            && range.end > self.text_summary.len
4542        {
4543            1
4544        } else {
4545            0
4546        };
4547
4548        let content_chunks = self.buffer.chunks(chunks_start..chunks_end, language_aware);
4549
4550        ExcerptChunks {
4551            excerpt_id: self.id,
4552            content_chunks,
4553            footer_height,
4554        }
4555    }
4556
4557    fn seek_chunks(&self, excerpt_chunks: &mut ExcerptChunks, range: Range<usize>) {
4558        let content_start = self.range.context.start.to_offset(&self.buffer);
4559        let chunks_start = content_start + range.start;
4560        let chunks_end = content_start + cmp::min(range.end, self.text_summary.len);
4561        excerpt_chunks.content_chunks.seek(chunks_start..chunks_end);
4562        excerpt_chunks.footer_height = if self.has_trailing_newline
4563            && range.start <= self.text_summary.len
4564            && range.end > self.text_summary.len
4565        {
4566            1
4567        } else {
4568            0
4569        };
4570    }
4571
4572    fn bytes_in_range(&self, range: Range<usize>) -> ExcerptBytes {
4573        let content_start = self.range.context.start.to_offset(&self.buffer);
4574        let bytes_start = content_start + range.start;
4575        let bytes_end = content_start + cmp::min(range.end, self.text_summary.len);
4576        let footer_height = if self.has_trailing_newline
4577            && range.start <= self.text_summary.len
4578            && range.end > self.text_summary.len
4579        {
4580            1
4581        } else {
4582            0
4583        };
4584        let content_bytes = self.buffer.bytes_in_range(bytes_start..bytes_end);
4585
4586        ExcerptBytes {
4587            content_bytes,
4588            padding_height: footer_height,
4589            reversed: false,
4590        }
4591    }
4592
4593    fn reversed_bytes_in_range(&self, range: Range<usize>) -> ExcerptBytes {
4594        let content_start = self.range.context.start.to_offset(&self.buffer);
4595        let bytes_start = content_start + range.start;
4596        let bytes_end = content_start + cmp::min(range.end, self.text_summary.len);
4597        let footer_height = if self.has_trailing_newline
4598            && range.start <= self.text_summary.len
4599            && range.end > self.text_summary.len
4600        {
4601            1
4602        } else {
4603            0
4604        };
4605        let content_bytes = self.buffer.reversed_bytes_in_range(bytes_start..bytes_end);
4606
4607        ExcerptBytes {
4608            content_bytes,
4609            padding_height: footer_height,
4610            reversed: true,
4611        }
4612    }
4613
4614    fn clip_anchor(&self, text_anchor: text::Anchor) -> text::Anchor {
4615        if text_anchor
4616            .cmp(&self.range.context.start, &self.buffer)
4617            .is_lt()
4618        {
4619            self.range.context.start
4620        } else if text_anchor
4621            .cmp(&self.range.context.end, &self.buffer)
4622            .is_gt()
4623        {
4624            self.range.context.end
4625        } else {
4626            text_anchor
4627        }
4628    }
4629
4630    fn contains(&self, anchor: &Anchor) -> bool {
4631        Some(self.buffer_id) == anchor.buffer_id
4632            && self
4633                .range
4634                .context
4635                .start
4636                .cmp(&anchor.text_anchor, &self.buffer)
4637                .is_le()
4638            && self
4639                .range
4640                .context
4641                .end
4642                .cmp(&anchor.text_anchor, &self.buffer)
4643                .is_ge()
4644    }
4645
4646    /// The [`Excerpt`]'s start offset in its [`Buffer`]
4647    fn buffer_start_offset(&self) -> usize {
4648        self.range.context.start.to_offset(&self.buffer)
4649    }
4650
4651    /// The [`Excerpt`]'s start point in its [`Buffer`]
4652    fn buffer_start_point(&self) -> Point {
4653        self.range.context.start.to_point(&self.buffer)
4654    }
4655
4656    /// The [`Excerpt`]'s end offset in its [`Buffer`]
4657    fn buffer_end_offset(&self) -> usize {
4658        self.buffer_start_offset() + self.text_summary.len
4659    }
4660}
4661
4662impl<'a> MultiBufferExcerpt<'a> {
4663    fn new(excerpt: &'a Excerpt, (excerpt_offset, excerpt_position): (usize, Point)) -> Self {
4664        MultiBufferExcerpt {
4665            excerpt,
4666            excerpt_offset,
4667            excerpt_position,
4668        }
4669    }
4670
4671    pub fn id(&self) -> ExcerptId {
4672        self.excerpt.id
4673    }
4674
4675    pub fn buffer_id(&self) -> BufferId {
4676        self.excerpt.buffer_id
4677    }
4678
4679    pub fn start_anchor(&self) -> Anchor {
4680        Anchor {
4681            buffer_id: Some(self.excerpt.buffer_id),
4682            excerpt_id: self.excerpt.id,
4683            text_anchor: self.excerpt.range.context.start,
4684        }
4685    }
4686
4687    pub fn end_anchor(&self) -> Anchor {
4688        Anchor {
4689            buffer_id: Some(self.excerpt.buffer_id),
4690            excerpt_id: self.excerpt.id,
4691            text_anchor: self.excerpt.range.context.end,
4692        }
4693    }
4694
4695    pub fn buffer(&self) -> &'a BufferSnapshot {
4696        &self.excerpt.buffer
4697    }
4698
4699    pub fn buffer_range(&self) -> Range<text::Anchor> {
4700        self.excerpt.range.context.clone()
4701    }
4702
4703    pub fn start_offset(&self) -> usize {
4704        self.excerpt_offset
4705    }
4706
4707    pub fn start_point(&self) -> Point {
4708        self.excerpt_position
4709    }
4710
4711    /// Maps an offset within the [`MultiBuffer`] to an offset within the [`Buffer`]
4712    pub fn map_offset_to_buffer(&self, offset: usize) -> usize {
4713        self.excerpt.buffer_start_offset()
4714            + offset
4715                .saturating_sub(self.excerpt_offset)
4716                .min(self.excerpt.text_summary.len)
4717    }
4718
4719    /// Maps a point within the [`MultiBuffer`] to a point within the [`Buffer`]
4720    pub fn map_point_to_buffer(&self, point: Point) -> Point {
4721        self.excerpt.buffer_start_point()
4722            + point
4723                .saturating_sub(self.excerpt_position)
4724                .min(self.excerpt.text_summary.lines)
4725    }
4726
4727    /// Maps a range within the [`MultiBuffer`] to a range within the [`Buffer`]
4728    pub fn map_range_to_buffer(&self, range: Range<usize>) -> Range<usize> {
4729        self.map_offset_to_buffer(range.start)..self.map_offset_to_buffer(range.end)
4730    }
4731
4732    /// Map an offset within the [`Buffer`] to an offset within the [`MultiBuffer`]
4733    pub fn map_offset_from_buffer(&self, buffer_offset: usize) -> usize {
4734        let buffer_offset_in_excerpt = buffer_offset
4735            .saturating_sub(self.excerpt.buffer_start_offset())
4736            .min(self.excerpt.text_summary.len);
4737        self.excerpt_offset + buffer_offset_in_excerpt
4738    }
4739
4740    /// Map a point within the [`Buffer`] to a point within the [`MultiBuffer`]
4741    pub fn map_point_from_buffer(&self, buffer_position: Point) -> Point {
4742        let position_in_excerpt = buffer_position.saturating_sub(self.excerpt.buffer_start_point());
4743        let position_in_excerpt =
4744            position_in_excerpt.min(self.excerpt.text_summary.lines + Point::new(1, 0));
4745        self.excerpt_position + position_in_excerpt
4746    }
4747
4748    /// Map a range within the [`Buffer`] to a range within the [`MultiBuffer`]
4749    pub fn map_range_from_buffer(&self, buffer_range: Range<usize>) -> Range<usize> {
4750        self.map_offset_from_buffer(buffer_range.start)
4751            ..self.map_offset_from_buffer(buffer_range.end)
4752    }
4753
4754    /// Returns true if the entirety of the given range is in the buffer's excerpt
4755    pub fn contains_buffer_range(&self, range: Range<usize>) -> bool {
4756        range.start >= self.excerpt.buffer_start_offset()
4757            && range.end <= self.excerpt.buffer_end_offset()
4758    }
4759
4760    pub fn max_buffer_row(&self) -> u32 {
4761        self.excerpt.max_buffer_row
4762    }
4763}
4764
4765impl ExcerptId {
4766    pub fn min() -> Self {
4767        Self(0)
4768    }
4769
4770    pub fn max() -> Self {
4771        Self(usize::MAX)
4772    }
4773
4774    pub fn to_proto(&self) -> u64 {
4775        self.0 as _
4776    }
4777
4778    pub fn from_proto(proto: u64) -> Self {
4779        Self(proto as _)
4780    }
4781
4782    pub fn cmp(&self, other: &Self, snapshot: &MultiBufferSnapshot) -> cmp::Ordering {
4783        let a = snapshot.excerpt_locator_for_id(*self);
4784        let b = snapshot.excerpt_locator_for_id(*other);
4785        a.cmp(b).then_with(|| self.0.cmp(&other.0))
4786    }
4787}
4788
4789impl From<ExcerptId> for usize {
4790    fn from(val: ExcerptId) -> Self {
4791        val.0
4792    }
4793}
4794
4795impl fmt::Debug for Excerpt {
4796    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
4797        f.debug_struct("Excerpt")
4798            .field("id", &self.id)
4799            .field("locator", &self.locator)
4800            .field("buffer_id", &self.buffer_id)
4801            .field("range", &self.range)
4802            .field("text_summary", &self.text_summary)
4803            .field("has_trailing_newline", &self.has_trailing_newline)
4804            .finish()
4805    }
4806}
4807
4808impl sum_tree::Item for Excerpt {
4809    type Summary = ExcerptSummary;
4810
4811    fn summary(&self, _cx: &()) -> Self::Summary {
4812        let mut text = self.text_summary.clone();
4813        if self.has_trailing_newline {
4814            text += TextSummary::from("\n");
4815        }
4816        ExcerptSummary {
4817            excerpt_id: self.id,
4818            excerpt_locator: self.locator.clone(),
4819            widest_line_number: self.max_buffer_row,
4820            text,
4821        }
4822    }
4823}
4824
4825impl sum_tree::Item for ExcerptIdMapping {
4826    type Summary = ExcerptId;
4827
4828    fn summary(&self, _cx: &()) -> Self::Summary {
4829        self.id
4830    }
4831}
4832
4833impl sum_tree::KeyedItem for ExcerptIdMapping {
4834    type Key = ExcerptId;
4835
4836    fn key(&self) -> Self::Key {
4837        self.id
4838    }
4839}
4840
4841impl sum_tree::Summary for ExcerptId {
4842    type Context = ();
4843
4844    fn zero(_cx: &()) -> Self {
4845        Default::default()
4846    }
4847
4848    fn add_summary(&mut self, other: &Self, _: &()) {
4849        *self = *other;
4850    }
4851}
4852
4853impl sum_tree::Summary for ExcerptSummary {
4854    type Context = ();
4855
4856    fn zero(_cx: &()) -> Self {
4857        Default::default()
4858    }
4859
4860    fn add_summary(&mut self, summary: &Self, _: &()) {
4861        debug_assert!(summary.excerpt_locator > self.excerpt_locator);
4862        self.excerpt_locator = summary.excerpt_locator.clone();
4863        self.text.add_summary(&summary.text, &());
4864        self.widest_line_number = cmp::max(self.widest_line_number, summary.widest_line_number);
4865    }
4866}
4867
4868impl<'a> sum_tree::Dimension<'a, ExcerptSummary> for TextSummary {
4869    fn zero(_cx: &()) -> Self {
4870        Default::default()
4871    }
4872
4873    fn add_summary(&mut self, summary: &'a ExcerptSummary, _: &()) {
4874        *self += &summary.text;
4875    }
4876}
4877
4878impl<'a> sum_tree::Dimension<'a, ExcerptSummary> for usize {
4879    fn zero(_cx: &()) -> Self {
4880        Default::default()
4881    }
4882
4883    fn add_summary(&mut self, summary: &'a ExcerptSummary, _: &()) {
4884        *self += summary.text.len;
4885    }
4886}
4887
4888impl<'a> sum_tree::SeekTarget<'a, ExcerptSummary, ExcerptSummary> for usize {
4889    fn cmp(&self, cursor_location: &ExcerptSummary, _: &()) -> cmp::Ordering {
4890        Ord::cmp(self, &cursor_location.text.len)
4891    }
4892}
4893
4894impl<'a> sum_tree::SeekTarget<'a, ExcerptSummary, TextSummary> for Point {
4895    fn cmp(&self, cursor_location: &TextSummary, _: &()) -> cmp::Ordering {
4896        Ord::cmp(self, &cursor_location.lines)
4897    }
4898}
4899
4900impl<'a> sum_tree::SeekTarget<'a, ExcerptSummary, Option<&'a Locator>> for Locator {
4901    fn cmp(&self, cursor_location: &Option<&'a Locator>, _: &()) -> cmp::Ordering {
4902        Ord::cmp(&Some(self), cursor_location)
4903    }
4904}
4905
4906impl<'a> sum_tree::SeekTarget<'a, ExcerptSummary, ExcerptSummary> for Locator {
4907    fn cmp(&self, cursor_location: &ExcerptSummary, _: &()) -> cmp::Ordering {
4908        Ord::cmp(self, &cursor_location.excerpt_locator)
4909    }
4910}
4911
4912impl<'a> sum_tree::Dimension<'a, ExcerptSummary> for OffsetUtf16 {
4913    fn zero(_cx: &()) -> Self {
4914        Default::default()
4915    }
4916
4917    fn add_summary(&mut self, summary: &'a ExcerptSummary, _: &()) {
4918        *self += summary.text.len_utf16;
4919    }
4920}
4921
4922impl<'a> sum_tree::Dimension<'a, ExcerptSummary> for Point {
4923    fn zero(_cx: &()) -> Self {
4924        Default::default()
4925    }
4926
4927    fn add_summary(&mut self, summary: &'a ExcerptSummary, _: &()) {
4928        *self += summary.text.lines;
4929    }
4930}
4931
4932impl<'a> sum_tree::Dimension<'a, ExcerptSummary> for PointUtf16 {
4933    fn zero(_cx: &()) -> Self {
4934        Default::default()
4935    }
4936
4937    fn add_summary(&mut self, summary: &'a ExcerptSummary, _: &()) {
4938        *self += summary.text.lines_utf16()
4939    }
4940}
4941
4942impl<'a> sum_tree::Dimension<'a, ExcerptSummary> for Option<&'a Locator> {
4943    fn zero(_cx: &()) -> Self {
4944        Default::default()
4945    }
4946
4947    fn add_summary(&mut self, summary: &'a ExcerptSummary, _: &()) {
4948        *self = Some(&summary.excerpt_locator);
4949    }
4950}
4951
4952impl<'a> sum_tree::Dimension<'a, ExcerptSummary> for Option<ExcerptId> {
4953    fn zero(_cx: &()) -> Self {
4954        Default::default()
4955    }
4956
4957    fn add_summary(&mut self, summary: &'a ExcerptSummary, _: &()) {
4958        *self = Some(summary.excerpt_id);
4959    }
4960}
4961
4962impl<'a> MultiBufferRows<'a> {
4963    pub fn seek(&mut self, row: MultiBufferRow) {
4964        self.buffer_row_range = 0..0;
4965
4966        self.excerpts
4967            .seek_forward(&Point::new(row.0, 0), Bias::Right, &());
4968        if self.excerpts.item().is_none() {
4969            self.excerpts.prev(&());
4970
4971            if self.excerpts.item().is_none() && row.0 == 0 {
4972                self.buffer_row_range = 0..1;
4973                return;
4974            }
4975        }
4976
4977        if let Some(excerpt) = self.excerpts.item() {
4978            let overshoot = row.0 - self.excerpts.start().row;
4979            let excerpt_start = excerpt.range.context.start.to_point(&excerpt.buffer).row;
4980            self.buffer_row_range.start = excerpt_start + overshoot;
4981            self.buffer_row_range.end = excerpt_start + excerpt.text_summary.lines.row + 1;
4982        }
4983    }
4984}
4985
4986impl<'a> Iterator for MultiBufferRows<'a> {
4987    type Item = Option<u32>;
4988
4989    fn next(&mut self) -> Option<Self::Item> {
4990        loop {
4991            if !self.buffer_row_range.is_empty() {
4992                let row = Some(self.buffer_row_range.start);
4993                self.buffer_row_range.start += 1;
4994                return Some(row);
4995            }
4996            self.excerpts.item()?;
4997            self.excerpts.next(&());
4998            let excerpt = self.excerpts.item()?;
4999            self.buffer_row_range.start = excerpt.range.context.start.to_point(&excerpt.buffer).row;
5000            self.buffer_row_range.end =
5001                self.buffer_row_range.start + excerpt.text_summary.lines.row + 1;
5002        }
5003    }
5004}
5005
5006impl<'a> MultiBufferChunks<'a> {
5007    pub fn offset(&self) -> usize {
5008        self.range.start
5009    }
5010
5011    pub fn seek(&mut self, new_range: Range<usize>) {
5012        self.range = new_range.clone();
5013        self.excerpts.seek(&new_range.start, Bias::Right, &());
5014        if let Some(excerpt) = self.excerpts.item() {
5015            let excerpt_start = self.excerpts.start();
5016            if let Some(excerpt_chunks) = self
5017                .excerpt_chunks
5018                .as_mut()
5019                .filter(|chunks| excerpt.id == chunks.excerpt_id)
5020            {
5021                excerpt.seek_chunks(
5022                    excerpt_chunks,
5023                    self.range.start - excerpt_start..self.range.end - excerpt_start,
5024                );
5025            } else {
5026                self.excerpt_chunks = Some(excerpt.chunks_in_range(
5027                    self.range.start - excerpt_start..self.range.end - excerpt_start,
5028                    self.language_aware,
5029                ));
5030            }
5031        } else {
5032            self.excerpt_chunks = None;
5033        }
5034    }
5035}
5036
5037impl<'a> Iterator for MultiBufferChunks<'a> {
5038    type Item = Chunk<'a>;
5039
5040    fn next(&mut self) -> Option<Self::Item> {
5041        if self.range.is_empty() {
5042            None
5043        } else if let Some(chunk) = self.excerpt_chunks.as_mut()?.next() {
5044            self.range.start += chunk.text.len();
5045            Some(chunk)
5046        } else {
5047            self.excerpts.next(&());
5048            let excerpt = self.excerpts.item()?;
5049            self.excerpt_chunks = Some(excerpt.chunks_in_range(
5050                0..self.range.end - self.excerpts.start(),
5051                self.language_aware,
5052            ));
5053            self.next()
5054        }
5055    }
5056}
5057
5058impl<'a> MultiBufferBytes<'a> {
5059    fn consume(&mut self, len: usize) {
5060        self.range.start += len;
5061        self.chunk = &self.chunk[len..];
5062
5063        if !self.range.is_empty() && self.chunk.is_empty() {
5064            if let Some(chunk) = self.excerpt_bytes.as_mut().and_then(|bytes| bytes.next()) {
5065                self.chunk = chunk;
5066            } else {
5067                self.excerpts.next(&());
5068                if let Some(excerpt) = self.excerpts.item() {
5069                    let mut excerpt_bytes =
5070                        excerpt.bytes_in_range(0..self.range.end - self.excerpts.start());
5071                    self.chunk = excerpt_bytes.next().unwrap();
5072                    self.excerpt_bytes = Some(excerpt_bytes);
5073                }
5074            }
5075        }
5076    }
5077}
5078
5079impl<'a> Iterator for MultiBufferBytes<'a> {
5080    type Item = &'a [u8];
5081
5082    fn next(&mut self) -> Option<Self::Item> {
5083        let chunk = self.chunk;
5084        if chunk.is_empty() {
5085            None
5086        } else {
5087            self.consume(chunk.len());
5088            Some(chunk)
5089        }
5090    }
5091}
5092
5093impl<'a> io::Read for MultiBufferBytes<'a> {
5094    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
5095        let len = cmp::min(buf.len(), self.chunk.len());
5096        buf[..len].copy_from_slice(&self.chunk[..len]);
5097        if len > 0 {
5098            self.consume(len);
5099        }
5100        Ok(len)
5101    }
5102}
5103
5104impl<'a> ReversedMultiBufferBytes<'a> {
5105    fn consume(&mut self, len: usize) {
5106        self.range.end -= len;
5107        self.chunk = &self.chunk[..self.chunk.len() - len];
5108
5109        if !self.range.is_empty() && self.chunk.is_empty() {
5110            if let Some(chunk) = self.excerpt_bytes.as_mut().and_then(|bytes| bytes.next()) {
5111                self.chunk = chunk;
5112            } else {
5113                self.excerpts.prev(&());
5114                if let Some(excerpt) = self.excerpts.item() {
5115                    let mut excerpt_bytes = excerpt.reversed_bytes_in_range(
5116                        self.range.start.saturating_sub(*self.excerpts.start())..usize::MAX,
5117                    );
5118                    self.chunk = excerpt_bytes.next().unwrap();
5119                    self.excerpt_bytes = Some(excerpt_bytes);
5120                }
5121            }
5122        }
5123    }
5124}
5125
5126impl<'a> io::Read for ReversedMultiBufferBytes<'a> {
5127    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
5128        let len = cmp::min(buf.len(), self.chunk.len());
5129        buf[..len].copy_from_slice(&self.chunk[..len]);
5130        buf[..len].reverse();
5131        if len > 0 {
5132            self.consume(len);
5133        }
5134        Ok(len)
5135    }
5136}
5137impl<'a> Iterator for ExcerptBytes<'a> {
5138    type Item = &'a [u8];
5139
5140    fn next(&mut self) -> Option<Self::Item> {
5141        if self.reversed && self.padding_height > 0 {
5142            let result = &NEWLINES[..self.padding_height];
5143            self.padding_height = 0;
5144            return Some(result);
5145        }
5146
5147        if let Some(chunk) = self.content_bytes.next() {
5148            if !chunk.is_empty() {
5149                return Some(chunk);
5150            }
5151        }
5152
5153        if self.padding_height > 0 {
5154            let result = &NEWLINES[..self.padding_height];
5155            self.padding_height = 0;
5156            return Some(result);
5157        }
5158
5159        None
5160    }
5161}
5162
5163impl<'a> Iterator for ExcerptChunks<'a> {
5164    type Item = Chunk<'a>;
5165
5166    fn next(&mut self) -> Option<Self::Item> {
5167        if let Some(chunk) = self.content_chunks.next() {
5168            return Some(chunk);
5169        }
5170
5171        if self.footer_height > 0 {
5172            let text = unsafe { str::from_utf8_unchecked(&NEWLINES[..self.footer_height]) };
5173            self.footer_height = 0;
5174            return Some(Chunk {
5175                text,
5176                ..Default::default()
5177            });
5178        }
5179
5180        None
5181    }
5182}
5183
5184impl ToOffset for Point {
5185    fn to_offset<'a>(&self, snapshot: &MultiBufferSnapshot) -> usize {
5186        snapshot.point_to_offset(*self)
5187    }
5188}
5189
5190impl ToOffset for usize {
5191    fn to_offset<'a>(&self, snapshot: &MultiBufferSnapshot) -> usize {
5192        assert!(*self <= snapshot.len(), "offset is out of range");
5193        *self
5194    }
5195}
5196
5197impl ToOffset for OffsetUtf16 {
5198    fn to_offset<'a>(&self, snapshot: &MultiBufferSnapshot) -> usize {
5199        snapshot.offset_utf16_to_offset(*self)
5200    }
5201}
5202
5203impl ToOffset for PointUtf16 {
5204    fn to_offset<'a>(&self, snapshot: &MultiBufferSnapshot) -> usize {
5205        snapshot.point_utf16_to_offset(*self)
5206    }
5207}
5208
5209impl ToOffsetUtf16 for OffsetUtf16 {
5210    fn to_offset_utf16(&self, _snapshot: &MultiBufferSnapshot) -> OffsetUtf16 {
5211        *self
5212    }
5213}
5214
5215impl ToOffsetUtf16 for usize {
5216    fn to_offset_utf16(&self, snapshot: &MultiBufferSnapshot) -> OffsetUtf16 {
5217        snapshot.offset_to_offset_utf16(*self)
5218    }
5219}
5220
5221impl ToPoint for usize {
5222    fn to_point<'a>(&self, snapshot: &MultiBufferSnapshot) -> Point {
5223        snapshot.offset_to_point(*self)
5224    }
5225}
5226
5227impl ToPoint for Point {
5228    fn to_point<'a>(&self, _: &MultiBufferSnapshot) -> Point {
5229        *self
5230    }
5231}
5232
5233impl ToPointUtf16 for usize {
5234    fn to_point_utf16<'a>(&self, snapshot: &MultiBufferSnapshot) -> PointUtf16 {
5235        snapshot.offset_to_point_utf16(*self)
5236    }
5237}
5238
5239impl ToPointUtf16 for Point {
5240    fn to_point_utf16<'a>(&self, snapshot: &MultiBufferSnapshot) -> PointUtf16 {
5241        snapshot.point_to_point_utf16(*self)
5242    }
5243}
5244
5245impl ToPointUtf16 for PointUtf16 {
5246    fn to_point_utf16<'a>(&self, _: &MultiBufferSnapshot) -> PointUtf16 {
5247        *self
5248    }
5249}
5250
5251pub fn build_excerpt_ranges<T>(
5252    buffer: &BufferSnapshot,
5253    ranges: &[Range<T>],
5254    context_line_count: u32,
5255) -> (Vec<ExcerptRange<Point>>, Vec<usize>)
5256where
5257    T: text::ToPoint,
5258{
5259    let max_point = buffer.max_point();
5260    let mut range_counts = Vec::new();
5261    let mut excerpt_ranges = Vec::new();
5262    let mut range_iter = ranges
5263        .iter()
5264        .map(|range| range.start.to_point(buffer)..range.end.to_point(buffer))
5265        .peekable();
5266    while let Some(range) = range_iter.next() {
5267        let excerpt_start = Point::new(range.start.row.saturating_sub(context_line_count), 0);
5268        let row = (range.end.row + context_line_count).min(max_point.row);
5269        let mut excerpt_end = Point::new(row, buffer.line_len(row));
5270
5271        let mut ranges_in_excerpt = 1;
5272
5273        while let Some(next_range) = range_iter.peek() {
5274            if next_range.start.row <= excerpt_end.row + context_line_count {
5275                let row = (next_range.end.row + context_line_count).min(max_point.row);
5276                excerpt_end = Point::new(row, buffer.line_len(row));
5277
5278                ranges_in_excerpt += 1;
5279                range_iter.next();
5280            } else {
5281                break;
5282            }
5283        }
5284
5285        excerpt_ranges.push(ExcerptRange {
5286            context: excerpt_start..excerpt_end,
5287            primary: Some(range),
5288        });
5289        range_counts.push(ranges_in_excerpt);
5290    }
5291
5292    (excerpt_ranges, range_counts)
5293}