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)]
 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 range_to_buffer_ranges<T: ToOffset>(
1671        &self,
1672        range: Range<T>,
1673        cx: &AppContext,
1674    ) -> Vec<(Model<Buffer>, Range<usize>, ExcerptId)> {
1675        let snapshot = self.read(cx);
1676        let start = range.start.to_offset(&snapshot);
1677        let end = range.end.to_offset(&snapshot);
1678
1679        let mut result = Vec::new();
1680        let mut cursor = snapshot.excerpts.cursor::<usize>(&());
1681        cursor.seek(&start, Bias::Right, &());
1682        if cursor.item().is_none() {
1683            cursor.prev(&());
1684        }
1685
1686        while let Some(excerpt) = cursor.item() {
1687            if *cursor.start() > end {
1688                break;
1689            }
1690
1691            let mut end_before_newline = cursor.end(&());
1692            if excerpt.has_trailing_newline {
1693                end_before_newline -= 1;
1694            }
1695            let excerpt_start = excerpt.range.context.start.to_offset(&excerpt.buffer);
1696            let start = excerpt_start + (cmp::max(start, *cursor.start()) - *cursor.start());
1697            let end = excerpt_start + (cmp::min(end, end_before_newline) - *cursor.start());
1698            let buffer = self.buffers.borrow()[&excerpt.buffer_id].buffer.clone();
1699            result.push((buffer, start..end, excerpt.id));
1700            cursor.next(&());
1701        }
1702
1703        result
1704    }
1705
1706    pub fn remove_excerpts(
1707        &mut self,
1708        excerpt_ids: impl IntoIterator<Item = ExcerptId>,
1709        cx: &mut ModelContext<Self>,
1710    ) {
1711        self.sync(cx);
1712        let ids = excerpt_ids.into_iter().collect::<Vec<_>>();
1713        if ids.is_empty() {
1714            return;
1715        }
1716
1717        let mut buffers = self.buffers.borrow_mut();
1718        let mut snapshot = self.snapshot.borrow_mut();
1719        let mut new_excerpts = SumTree::default();
1720        let mut cursor = snapshot.excerpts.cursor::<(Option<&Locator>, usize)>(&());
1721        let mut edits = Vec::new();
1722        let mut excerpt_ids = ids.iter().copied().peekable();
1723
1724        while let Some(excerpt_id) = excerpt_ids.next() {
1725            // Seek to the next excerpt to remove, preserving any preceding excerpts.
1726            let locator = snapshot.excerpt_locator_for_id(excerpt_id);
1727            new_excerpts.append(cursor.slice(&Some(locator), Bias::Left, &()), &());
1728
1729            if let Some(mut excerpt) = cursor.item() {
1730                if excerpt.id != excerpt_id {
1731                    continue;
1732                }
1733                let mut old_start = cursor.start().1;
1734
1735                // Skip over the removed excerpt.
1736                'remove_excerpts: loop {
1737                    if let Some(buffer_state) = buffers.get_mut(&excerpt.buffer_id) {
1738                        buffer_state.excerpts.retain(|l| l != &excerpt.locator);
1739                        if buffer_state.excerpts.is_empty() {
1740                            buffers.remove(&excerpt.buffer_id);
1741                        }
1742                    }
1743                    cursor.next(&());
1744
1745                    // Skip over any subsequent excerpts that are also removed.
1746                    if let Some(&next_excerpt_id) = excerpt_ids.peek() {
1747                        let next_locator = snapshot.excerpt_locator_for_id(next_excerpt_id);
1748                        if let Some(next_excerpt) = cursor.item() {
1749                            if next_excerpt.locator == *next_locator {
1750                                excerpt_ids.next();
1751                                excerpt = next_excerpt;
1752                                continue 'remove_excerpts;
1753                            }
1754                        }
1755                    }
1756
1757                    break;
1758                }
1759
1760                // When removing the last excerpt, remove the trailing newline from
1761                // the previous excerpt.
1762                if cursor.item().is_none() && old_start > 0 {
1763                    old_start -= 1;
1764                    new_excerpts.update_last(|e| e.has_trailing_newline = false, &());
1765                }
1766
1767                // Push an edit for the removal of this run of excerpts.
1768                let old_end = cursor.start().1;
1769                let new_start = new_excerpts.summary().text.len;
1770                edits.push(Edit {
1771                    old: old_start..old_end,
1772                    new: new_start..new_start,
1773                });
1774            }
1775        }
1776        let suffix = cursor.suffix(&());
1777        let changed_trailing_excerpt = suffix.is_empty();
1778        new_excerpts.append(suffix, &());
1779        drop(cursor);
1780        snapshot.excerpts = new_excerpts;
1781
1782        if changed_trailing_excerpt {
1783            snapshot.trailing_excerpt_update_count += 1;
1784        }
1785
1786        self.subscriptions.publish_mut(edits);
1787        cx.emit(Event::Edited {
1788            singleton_buffer_edited: false,
1789            edited_buffer: None,
1790        });
1791        cx.emit(Event::ExcerptsRemoved { ids });
1792        cx.notify();
1793    }
1794
1795    pub fn wait_for_anchors<'a>(
1796        &self,
1797        anchors: impl 'a + Iterator<Item = Anchor>,
1798        cx: &mut ModelContext<Self>,
1799    ) -> impl 'static + Future<Output = Result<()>> {
1800        let borrow = self.buffers.borrow();
1801        let mut error = None;
1802        let mut futures = Vec::new();
1803        for anchor in anchors {
1804            if let Some(buffer_id) = anchor.buffer_id {
1805                if let Some(buffer) = borrow.get(&buffer_id) {
1806                    buffer.buffer.update(cx, |buffer, _| {
1807                        futures.push(buffer.wait_for_anchors([anchor.text_anchor]))
1808                    });
1809                } else {
1810                    error = Some(anyhow!(
1811                        "buffer {buffer_id} is not part of this multi-buffer"
1812                    ));
1813                    break;
1814                }
1815            }
1816        }
1817        async move {
1818            if let Some(error) = error {
1819                Err(error)?;
1820            }
1821            for future in futures {
1822                future.await?;
1823            }
1824            Ok(())
1825        }
1826    }
1827
1828    pub fn text_anchor_for_position<T: ToOffset>(
1829        &self,
1830        position: T,
1831        cx: &AppContext,
1832    ) -> Option<(Model<Buffer>, language::Anchor)> {
1833        let snapshot = self.read(cx);
1834        let anchor = snapshot.anchor_before(position);
1835        let buffer = self
1836            .buffers
1837            .borrow()
1838            .get(&anchor.buffer_id?)?
1839            .buffer
1840            .clone();
1841        Some((buffer, anchor.text_anchor))
1842    }
1843
1844    fn on_buffer_event(
1845        &mut self,
1846        buffer: Model<Buffer>,
1847        event: &language::BufferEvent,
1848        cx: &mut ModelContext<Self>,
1849    ) {
1850        cx.emit(match event {
1851            language::BufferEvent::Edited => Event::Edited {
1852                singleton_buffer_edited: true,
1853                edited_buffer: Some(buffer.clone()),
1854            },
1855            language::BufferEvent::DirtyChanged => Event::DirtyChanged,
1856            language::BufferEvent::Saved => Event::Saved,
1857            language::BufferEvent::FileHandleChanged => Event::FileHandleChanged,
1858            language::BufferEvent::Reloaded => Event::Reloaded,
1859            language::BufferEvent::ReloadNeeded => Event::ReloadNeeded,
1860            language::BufferEvent::LanguageChanged => {
1861                Event::LanguageChanged(buffer.read(cx).remote_id())
1862            }
1863            language::BufferEvent::Reparsed => Event::Reparsed(buffer.read(cx).remote_id()),
1864            language::BufferEvent::DiagnosticsUpdated => Event::DiagnosticsUpdated,
1865            language::BufferEvent::Closed => Event::Closed,
1866            language::BufferEvent::Discarded => Event::Discarded,
1867            language::BufferEvent::CapabilityChanged => {
1868                self.capability = buffer.read(cx).capability();
1869                Event::CapabilityChanged
1870            }
1871            //
1872            language::BufferEvent::Operation { .. } => return,
1873        });
1874    }
1875
1876    pub fn all_buffers(&self) -> HashSet<Model<Buffer>> {
1877        self.buffers
1878            .borrow()
1879            .values()
1880            .map(|state| state.buffer.clone())
1881            .collect()
1882    }
1883
1884    pub fn buffer(&self, buffer_id: BufferId) -> Option<Model<Buffer>> {
1885        self.buffers
1886            .borrow()
1887            .get(&buffer_id)
1888            .map(|state| state.buffer.clone())
1889    }
1890
1891    pub fn language_at<T: ToOffset>(&self, point: T, cx: &AppContext) -> Option<Arc<Language>> {
1892        self.point_to_buffer_offset(point, cx)
1893            .and_then(|(buffer, offset, _)| buffer.read(cx).language_at(offset))
1894    }
1895
1896    pub fn settings_at<'a, T: ToOffset>(
1897        &self,
1898        point: T,
1899        cx: &'a AppContext,
1900    ) -> Cow<'a, LanguageSettings> {
1901        let mut language = None;
1902        let mut file = None;
1903        if let Some((buffer, offset, _)) = self.point_to_buffer_offset(point, cx) {
1904            let buffer = buffer.read(cx);
1905            language = buffer.language_at(offset);
1906            file = buffer.file();
1907        }
1908        language_settings(language.map(|l| l.name()), file, cx)
1909    }
1910
1911    pub fn for_each_buffer(&self, mut f: impl FnMut(&Model<Buffer>)) {
1912        self.buffers
1913            .borrow()
1914            .values()
1915            .for_each(|state| f(&state.buffer))
1916    }
1917
1918    pub fn title<'a>(&'a self, cx: &'a AppContext) -> Cow<'a, str> {
1919        if let Some(title) = self.title.as_ref() {
1920            return title.into();
1921        }
1922
1923        if let Some(buffer) = self.as_singleton() {
1924            if let Some(file) = buffer.read(cx).file() {
1925                return file.file_name(cx).to_string_lossy();
1926            }
1927        }
1928
1929        "untitled".into()
1930    }
1931
1932    pub fn set_title(&mut self, title: String, cx: &mut ModelContext<Self>) {
1933        self.title = Some(title);
1934        cx.notify();
1935    }
1936
1937    /// Preserve preview tabs containing this multibuffer until additional edits occur.
1938    pub fn refresh_preview(&self, cx: &mut ModelContext<Self>) {
1939        for buffer_state in self.buffers.borrow().values() {
1940            buffer_state
1941                .buffer
1942                .update(cx, |buffer, _cx| buffer.refresh_preview());
1943        }
1944    }
1945
1946    /// Whether we should preserve the preview status of a tab containing this multi-buffer.
1947    pub fn preserve_preview(&self, cx: &AppContext) -> bool {
1948        self.buffers
1949            .borrow()
1950            .values()
1951            .all(|state| state.buffer.read(cx).preserve_preview())
1952    }
1953
1954    #[cfg(any(test, feature = "test-support"))]
1955    pub fn is_parsing(&self, cx: &AppContext) -> bool {
1956        self.as_singleton().unwrap().read(cx).is_parsing()
1957    }
1958
1959    pub fn resize_excerpt(
1960        &mut self,
1961        id: ExcerptId,
1962        range: Range<text::Anchor>,
1963        cx: &mut ModelContext<Self>,
1964    ) {
1965        self.sync(cx);
1966
1967        let snapshot = self.snapshot(cx);
1968        let locator = snapshot.excerpt_locator_for_id(id);
1969        let mut new_excerpts = SumTree::default();
1970        let mut cursor = snapshot.excerpts.cursor::<(Option<&Locator>, usize)>(&());
1971        let mut edits = Vec::<Edit<usize>>::new();
1972
1973        let prefix = cursor.slice(&Some(locator), Bias::Left, &());
1974        new_excerpts.append(prefix, &());
1975
1976        let mut excerpt = cursor.item().unwrap().clone();
1977        let old_text_len = excerpt.text_summary.len;
1978
1979        excerpt.range.context.start = range.start;
1980        excerpt.range.context.end = range.end;
1981        excerpt.max_buffer_row = range.end.to_point(&excerpt.buffer).row;
1982
1983        excerpt.text_summary = excerpt
1984            .buffer
1985            .text_summary_for_range(excerpt.range.context.clone());
1986
1987        let new_start_offset = new_excerpts.summary().text.len;
1988        let old_start_offset = cursor.start().1;
1989        let edit = Edit {
1990            old: old_start_offset..old_start_offset + old_text_len,
1991            new: new_start_offset..new_start_offset + excerpt.text_summary.len,
1992        };
1993
1994        if let Some(last_edit) = edits.last_mut() {
1995            if last_edit.old.end == edit.old.start {
1996                last_edit.old.end = edit.old.end;
1997                last_edit.new.end = edit.new.end;
1998            } else {
1999                edits.push(edit);
2000            }
2001        } else {
2002            edits.push(edit);
2003        }
2004
2005        new_excerpts.push(excerpt, &());
2006
2007        cursor.next(&());
2008
2009        new_excerpts.append(cursor.suffix(&()), &());
2010
2011        drop(cursor);
2012        self.snapshot.borrow_mut().excerpts = new_excerpts;
2013
2014        self.subscriptions.publish_mut(edits);
2015        cx.emit(Event::Edited {
2016            singleton_buffer_edited: false,
2017            edited_buffer: None,
2018        });
2019        cx.emit(Event::ExcerptsExpanded { ids: vec![id] });
2020        cx.notify();
2021    }
2022
2023    pub fn expand_excerpts(
2024        &mut self,
2025        ids: impl IntoIterator<Item = ExcerptId>,
2026        line_count: u32,
2027        direction: ExpandExcerptDirection,
2028        cx: &mut ModelContext<Self>,
2029    ) {
2030        if line_count == 0 {
2031            return;
2032        }
2033        self.sync(cx);
2034
2035        let ids = ids.into_iter().collect::<Vec<_>>();
2036        let snapshot = self.snapshot(cx);
2037        let locators = snapshot.excerpt_locators_for_ids(ids.iter().copied());
2038        let mut new_excerpts = SumTree::default();
2039        let mut cursor = snapshot.excerpts.cursor::<(Option<&Locator>, usize)>(&());
2040        let mut edits = Vec::<Edit<usize>>::new();
2041
2042        for locator in &locators {
2043            let prefix = cursor.slice(&Some(locator), Bias::Left, &());
2044            new_excerpts.append(prefix, &());
2045
2046            let mut excerpt = cursor.item().unwrap().clone();
2047            let old_text_len = excerpt.text_summary.len;
2048
2049            let up_line_count = if direction.should_expand_up() {
2050                line_count
2051            } else {
2052                0
2053            };
2054
2055            let start_row = excerpt
2056                .range
2057                .context
2058                .start
2059                .to_point(&excerpt.buffer)
2060                .row
2061                .saturating_sub(up_line_count);
2062            let start_point = Point::new(start_row, 0);
2063            excerpt.range.context.start = excerpt.buffer.anchor_before(start_point);
2064
2065            let down_line_count = if direction.should_expand_down() {
2066                line_count
2067            } else {
2068                0
2069            };
2070
2071            let mut end_point = excerpt.buffer.clip_point(
2072                excerpt.range.context.end.to_point(&excerpt.buffer)
2073                    + Point::new(down_line_count, 0),
2074                Bias::Left,
2075            );
2076            end_point.column = excerpt.buffer.line_len(end_point.row);
2077            excerpt.range.context.end = excerpt.buffer.anchor_after(end_point);
2078            excerpt.max_buffer_row = end_point.row;
2079
2080            excerpt.text_summary = excerpt
2081                .buffer
2082                .text_summary_for_range(excerpt.range.context.clone());
2083
2084            let new_start_offset = new_excerpts.summary().text.len;
2085            let old_start_offset = cursor.start().1;
2086            let edit = Edit {
2087                old: old_start_offset..old_start_offset + old_text_len,
2088                new: new_start_offset..new_start_offset + excerpt.text_summary.len,
2089            };
2090
2091            if let Some(last_edit) = edits.last_mut() {
2092                if last_edit.old.end == edit.old.start {
2093                    last_edit.old.end = edit.old.end;
2094                    last_edit.new.end = edit.new.end;
2095                } else {
2096                    edits.push(edit);
2097                }
2098            } else {
2099                edits.push(edit);
2100            }
2101
2102            new_excerpts.push(excerpt, &());
2103
2104            cursor.next(&());
2105        }
2106
2107        new_excerpts.append(cursor.suffix(&()), &());
2108
2109        drop(cursor);
2110        self.snapshot.borrow_mut().excerpts = new_excerpts;
2111
2112        self.subscriptions.publish_mut(edits);
2113        cx.emit(Event::Edited {
2114            singleton_buffer_edited: false,
2115            edited_buffer: None,
2116        });
2117        cx.emit(Event::ExcerptsExpanded { ids });
2118        cx.notify();
2119    }
2120
2121    fn sync(&self, cx: &AppContext) {
2122        let mut snapshot = self.snapshot.borrow_mut();
2123        let mut excerpts_to_edit = Vec::new();
2124        let mut non_text_state_updated = false;
2125        let mut is_dirty = false;
2126        let mut has_deleted_file = false;
2127        let mut has_conflict = false;
2128        let mut edited = false;
2129        let mut buffers = self.buffers.borrow_mut();
2130        for buffer_state in buffers.values_mut() {
2131            let buffer = buffer_state.buffer.read(cx);
2132            let version = buffer.version();
2133            let non_text_state_update_count = buffer.non_text_state_update_count();
2134
2135            let buffer_edited = version.changed_since(&buffer_state.last_version);
2136            let buffer_non_text_state_updated =
2137                non_text_state_update_count > buffer_state.last_non_text_state_update_count;
2138            if buffer_edited || buffer_non_text_state_updated {
2139                buffer_state.last_version = version;
2140                buffer_state.last_non_text_state_update_count = non_text_state_update_count;
2141                excerpts_to_edit.extend(
2142                    buffer_state
2143                        .excerpts
2144                        .iter()
2145                        .map(|locator| (locator, buffer_state.buffer.clone(), buffer_edited)),
2146                );
2147            }
2148
2149            edited |= buffer_edited;
2150            non_text_state_updated |= buffer_non_text_state_updated;
2151            is_dirty |= buffer.is_dirty();
2152            has_deleted_file |= buffer
2153                .file()
2154                .map_or(false, |file| file.disk_state() == DiskState::Deleted);
2155            has_conflict |= buffer.has_conflict();
2156        }
2157        if edited {
2158            snapshot.edit_count += 1;
2159        }
2160        if non_text_state_updated {
2161            snapshot.non_text_state_update_count += 1;
2162        }
2163        snapshot.is_dirty = is_dirty;
2164        snapshot.has_deleted_file = has_deleted_file;
2165        snapshot.has_conflict = has_conflict;
2166
2167        excerpts_to_edit.sort_unstable_by_key(|(locator, _, _)| *locator);
2168
2169        let mut edits = Vec::new();
2170        let mut new_excerpts = SumTree::default();
2171        let mut cursor = snapshot.excerpts.cursor::<(Option<&Locator>, usize)>(&());
2172
2173        for (locator, buffer, buffer_edited) in excerpts_to_edit {
2174            new_excerpts.append(cursor.slice(&Some(locator), Bias::Left, &()), &());
2175            let old_excerpt = cursor.item().unwrap();
2176            let buffer = buffer.read(cx);
2177            let buffer_id = buffer.remote_id();
2178
2179            let mut new_excerpt;
2180            if buffer_edited {
2181                edits.extend(
2182                    buffer
2183                        .edits_since_in_range::<usize>(
2184                            old_excerpt.buffer.version(),
2185                            old_excerpt.range.context.clone(),
2186                        )
2187                        .map(|mut edit| {
2188                            let excerpt_old_start = cursor.start().1;
2189                            let excerpt_new_start = new_excerpts.summary().text.len;
2190                            edit.old.start += excerpt_old_start;
2191                            edit.old.end += excerpt_old_start;
2192                            edit.new.start += excerpt_new_start;
2193                            edit.new.end += excerpt_new_start;
2194                            edit
2195                        }),
2196                );
2197
2198                new_excerpt = Excerpt::new(
2199                    old_excerpt.id,
2200                    locator.clone(),
2201                    buffer_id,
2202                    buffer.snapshot(),
2203                    old_excerpt.range.clone(),
2204                    old_excerpt.has_trailing_newline,
2205                );
2206            } else {
2207                new_excerpt = old_excerpt.clone();
2208                new_excerpt.buffer = buffer.snapshot();
2209            }
2210
2211            new_excerpts.push(new_excerpt, &());
2212            cursor.next(&());
2213        }
2214        new_excerpts.append(cursor.suffix(&()), &());
2215
2216        drop(cursor);
2217        snapshot.excerpts = new_excerpts;
2218
2219        self.subscriptions.publish(edits);
2220    }
2221}
2222
2223#[cfg(any(test, feature = "test-support"))]
2224impl MultiBuffer {
2225    pub fn build_simple(text: &str, cx: &mut gpui::AppContext) -> Model<Self> {
2226        let buffer = cx.new_model(|cx| Buffer::local(text, cx));
2227        cx.new_model(|cx| Self::singleton(buffer, cx))
2228    }
2229
2230    pub fn build_multi<const COUNT: usize>(
2231        excerpts: [(&str, Vec<Range<Point>>); COUNT],
2232        cx: &mut gpui::AppContext,
2233    ) -> Model<Self> {
2234        let multi = cx.new_model(|_| Self::new(Capability::ReadWrite));
2235        for (text, ranges) in excerpts {
2236            let buffer = cx.new_model(|cx| Buffer::local(text, cx));
2237            let excerpt_ranges = ranges.into_iter().map(|range| ExcerptRange {
2238                context: range,
2239                primary: None,
2240            });
2241            multi.update(cx, |multi, cx| {
2242                multi.push_excerpts(buffer, excerpt_ranges, cx)
2243            });
2244        }
2245
2246        multi
2247    }
2248
2249    pub fn build_from_buffer(buffer: Model<Buffer>, cx: &mut gpui::AppContext) -> Model<Self> {
2250        cx.new_model(|cx| Self::singleton(buffer, cx))
2251    }
2252
2253    pub fn build_random(rng: &mut impl rand::Rng, cx: &mut gpui::AppContext) -> Model<Self> {
2254        cx.new_model(|cx| {
2255            let mut multibuffer = MultiBuffer::new(Capability::ReadWrite);
2256            let mutation_count = rng.gen_range(1..=5);
2257            multibuffer.randomly_edit_excerpts(rng, mutation_count, cx);
2258            multibuffer
2259        })
2260    }
2261
2262    pub fn randomly_edit(
2263        &mut self,
2264        rng: &mut impl rand::Rng,
2265        edit_count: usize,
2266        cx: &mut ModelContext<Self>,
2267    ) {
2268        use util::RandomCharIter;
2269
2270        let snapshot = self.read(cx);
2271        let mut edits: Vec<(Range<usize>, Arc<str>)> = Vec::new();
2272        let mut last_end = None;
2273        for _ in 0..edit_count {
2274            if last_end.map_or(false, |last_end| last_end >= snapshot.len()) {
2275                break;
2276            }
2277
2278            let new_start = last_end.map_or(0, |last_end| last_end + 1);
2279            let end = snapshot.clip_offset(rng.gen_range(new_start..=snapshot.len()), Bias::Right);
2280            let start = snapshot.clip_offset(rng.gen_range(new_start..=end), Bias::Right);
2281            last_end = Some(end);
2282
2283            let mut range = start..end;
2284            if rng.gen_bool(0.2) {
2285                mem::swap(&mut range.start, &mut range.end);
2286            }
2287
2288            let new_text_len = rng.gen_range(0..10);
2289            let new_text: String = RandomCharIter::new(&mut *rng).take(new_text_len).collect();
2290
2291            edits.push((range, new_text.into()));
2292        }
2293        log::info!("mutating multi-buffer with {:?}", edits);
2294        drop(snapshot);
2295
2296        self.edit(edits, None, cx);
2297    }
2298
2299    pub fn randomly_edit_excerpts(
2300        &mut self,
2301        rng: &mut impl rand::Rng,
2302        mutation_count: usize,
2303        cx: &mut ModelContext<Self>,
2304    ) {
2305        use rand::prelude::*;
2306        use std::env;
2307        use util::RandomCharIter;
2308
2309        let max_excerpts = env::var("MAX_EXCERPTS")
2310            .map(|i| i.parse().expect("invalid `MAX_EXCERPTS` variable"))
2311            .unwrap_or(5);
2312
2313        let mut buffers = Vec::new();
2314        for _ in 0..mutation_count {
2315            if rng.gen_bool(0.05) {
2316                log::info!("Clearing multi-buffer");
2317                self.clear(cx);
2318                continue;
2319            } else if rng.gen_bool(0.1) && !self.excerpt_ids().is_empty() {
2320                let ids = self.excerpt_ids();
2321                let mut excerpts = HashSet::default();
2322                for _ in 0..rng.gen_range(0..ids.len()) {
2323                    excerpts.extend(ids.choose(rng).copied());
2324                }
2325
2326                let line_count = rng.gen_range(0..5);
2327
2328                log::info!("Expanding excerpts {excerpts:?} by {line_count} lines");
2329
2330                self.expand_excerpts(
2331                    excerpts.iter().cloned(),
2332                    line_count,
2333                    ExpandExcerptDirection::UpAndDown,
2334                    cx,
2335                );
2336                continue;
2337            }
2338
2339            let excerpt_ids = self.excerpt_ids();
2340            if excerpt_ids.is_empty() || (rng.gen() && excerpt_ids.len() < max_excerpts) {
2341                let buffer_handle = if rng.gen() || self.buffers.borrow().is_empty() {
2342                    let text = RandomCharIter::new(&mut *rng).take(10).collect::<String>();
2343                    buffers.push(cx.new_model(|cx| Buffer::local(text, cx)));
2344                    let buffer = buffers.last().unwrap().read(cx);
2345                    log::info!(
2346                        "Creating new buffer {} with text: {:?}",
2347                        buffer.remote_id(),
2348                        buffer.text()
2349                    );
2350                    buffers.last().unwrap().clone()
2351                } else {
2352                    self.buffers
2353                        .borrow()
2354                        .values()
2355                        .choose(rng)
2356                        .unwrap()
2357                        .buffer
2358                        .clone()
2359                };
2360
2361                let buffer = buffer_handle.read(cx);
2362                let buffer_text = buffer.text();
2363                let ranges = (0..rng.gen_range(0..5))
2364                    .map(|_| {
2365                        let end_ix =
2366                            buffer.clip_offset(rng.gen_range(0..=buffer.len()), Bias::Right);
2367                        let start_ix = buffer.clip_offset(rng.gen_range(0..=end_ix), Bias::Left);
2368                        ExcerptRange {
2369                            context: start_ix..end_ix,
2370                            primary: None,
2371                        }
2372                    })
2373                    .collect::<Vec<_>>();
2374                log::info!(
2375                    "Inserting excerpts from buffer {} and ranges {:?}: {:?}",
2376                    buffer_handle.read(cx).remote_id(),
2377                    ranges.iter().map(|r| &r.context).collect::<Vec<_>>(),
2378                    ranges
2379                        .iter()
2380                        .map(|r| &buffer_text[r.context.clone()])
2381                        .collect::<Vec<_>>()
2382                );
2383
2384                let excerpt_id = self.push_excerpts(buffer_handle.clone(), ranges, cx);
2385                log::info!("Inserted with ids: {:?}", excerpt_id);
2386            } else {
2387                let remove_count = rng.gen_range(1..=excerpt_ids.len());
2388                let mut excerpts_to_remove = excerpt_ids
2389                    .choose_multiple(rng, remove_count)
2390                    .cloned()
2391                    .collect::<Vec<_>>();
2392                let snapshot = self.snapshot.borrow();
2393                excerpts_to_remove.sort_unstable_by(|a, b| a.cmp(b, &snapshot));
2394                drop(snapshot);
2395                log::info!("Removing excerpts {:?}", excerpts_to_remove);
2396                self.remove_excerpts(excerpts_to_remove, cx);
2397            }
2398        }
2399    }
2400
2401    pub fn randomly_mutate(
2402        &mut self,
2403        rng: &mut impl rand::Rng,
2404        mutation_count: usize,
2405        cx: &mut ModelContext<Self>,
2406    ) {
2407        use rand::prelude::*;
2408
2409        if rng.gen_bool(0.7) || self.singleton {
2410            let buffer = self
2411                .buffers
2412                .borrow()
2413                .values()
2414                .choose(rng)
2415                .map(|state| state.buffer.clone());
2416
2417            if let Some(buffer) = buffer {
2418                buffer.update(cx, |buffer, cx| {
2419                    if rng.gen() {
2420                        buffer.randomly_edit(rng, mutation_count, cx);
2421                    } else {
2422                        buffer.randomly_undo_redo(rng, cx);
2423                    }
2424                });
2425            } else {
2426                self.randomly_edit(rng, mutation_count, cx);
2427            }
2428        } else {
2429            self.randomly_edit_excerpts(rng, mutation_count, cx);
2430        }
2431
2432        self.check_invariants(cx);
2433    }
2434
2435    fn check_invariants(&self, cx: &mut ModelContext<Self>) {
2436        let snapshot = self.read(cx);
2437        let excerpts = snapshot.excerpts.items(&());
2438        let excerpt_ids = snapshot.excerpt_ids.items(&());
2439
2440        for (ix, excerpt) in excerpts.iter().enumerate() {
2441            if ix == 0 {
2442                if excerpt.locator <= Locator::min() {
2443                    panic!("invalid first excerpt locator {:?}", excerpt.locator);
2444                }
2445            } else if excerpt.locator <= excerpts[ix - 1].locator {
2446                panic!("excerpts are out-of-order: {:?}", excerpts);
2447            }
2448        }
2449
2450        for (ix, entry) in excerpt_ids.iter().enumerate() {
2451            if ix == 0 {
2452                if entry.id.cmp(&ExcerptId::min(), &snapshot).is_le() {
2453                    panic!("invalid first excerpt id {:?}", entry.id);
2454                }
2455            } else if entry.id <= excerpt_ids[ix - 1].id {
2456                panic!("excerpt ids are out-of-order: {:?}", excerpt_ids);
2457            }
2458        }
2459    }
2460}
2461
2462impl EventEmitter<Event> for MultiBuffer {}
2463
2464impl MultiBufferSnapshot {
2465    pub fn text(&self) -> String {
2466        self.chunks(0..self.len(), false)
2467            .map(|chunk| chunk.text)
2468            .collect()
2469    }
2470
2471    pub fn reversed_chars_at<T: ToOffset>(&self, position: T) -> impl Iterator<Item = char> + '_ {
2472        let mut offset = position.to_offset(self);
2473        let mut cursor = self.excerpts.cursor::<usize>(&());
2474        cursor.seek(&offset, Bias::Left, &());
2475        let mut excerpt_chunks = cursor.item().map(|excerpt| {
2476            let end_before_footer = cursor.start() + excerpt.text_summary.len;
2477            let start = excerpt.range.context.start.to_offset(&excerpt.buffer);
2478            let end = start + (cmp::min(offset, end_before_footer) - cursor.start());
2479            excerpt.buffer.reversed_chunks_in_range(start..end)
2480        });
2481        iter::from_fn(move || {
2482            if offset == *cursor.start() {
2483                cursor.prev(&());
2484                let excerpt = cursor.item()?;
2485                excerpt_chunks = Some(
2486                    excerpt
2487                        .buffer
2488                        .reversed_chunks_in_range(excerpt.range.context.clone()),
2489                );
2490            }
2491
2492            let excerpt = cursor.item().unwrap();
2493            if offset == cursor.end(&()) && excerpt.has_trailing_newline {
2494                offset -= 1;
2495                Some("\n")
2496            } else {
2497                let chunk = excerpt_chunks.as_mut().unwrap().next().unwrap();
2498                offset -= chunk.len();
2499                Some(chunk)
2500            }
2501        })
2502        .flat_map(|c| c.chars().rev())
2503    }
2504
2505    pub fn chars_at<T: ToOffset>(&self, position: T) -> impl Iterator<Item = char> + '_ {
2506        let offset = position.to_offset(self);
2507        self.text_for_range(offset..self.len())
2508            .flat_map(|chunk| chunk.chars())
2509    }
2510
2511    pub fn text_for_range<T: ToOffset>(&self, range: Range<T>) -> impl Iterator<Item = &str> + '_ {
2512        self.chunks(range, false).map(|chunk| chunk.text)
2513    }
2514
2515    pub fn is_line_blank(&self, row: MultiBufferRow) -> bool {
2516        self.text_for_range(Point::new(row.0, 0)..Point::new(row.0, self.line_len(row)))
2517            .all(|chunk| chunk.matches(|c: char| !c.is_whitespace()).next().is_none())
2518    }
2519
2520    pub fn contains_str_at<T>(&self, position: T, needle: &str) -> bool
2521    where
2522        T: ToOffset,
2523    {
2524        let position = position.to_offset(self);
2525        position == self.clip_offset(position, Bias::Left)
2526            && self
2527                .bytes_in_range(position..self.len())
2528                .flatten()
2529                .copied()
2530                .take(needle.len())
2531                .eq(needle.bytes())
2532    }
2533
2534    pub fn surrounding_word<T: ToOffset>(
2535        &self,
2536        start: T,
2537        for_completion: bool,
2538    ) -> (Range<usize>, Option<CharKind>) {
2539        let mut start = start.to_offset(self);
2540        let mut end = start;
2541        let mut next_chars = self.chars_at(start).peekable();
2542        let mut prev_chars = self.reversed_chars_at(start).peekable();
2543
2544        let classifier = self
2545            .char_classifier_at(start)
2546            .for_completion(for_completion);
2547
2548        let word_kind = cmp::max(
2549            prev_chars.peek().copied().map(|c| classifier.kind(c)),
2550            next_chars.peek().copied().map(|c| classifier.kind(c)),
2551        );
2552
2553        for ch in prev_chars {
2554            if Some(classifier.kind(ch)) == word_kind && ch != '\n' {
2555                start -= ch.len_utf8();
2556            } else {
2557                break;
2558            }
2559        }
2560
2561        for ch in next_chars {
2562            if Some(classifier.kind(ch)) == word_kind && ch != '\n' {
2563                end += ch.len_utf8();
2564            } else {
2565                break;
2566            }
2567        }
2568
2569        (start..end, word_kind)
2570    }
2571
2572    pub fn as_singleton(&self) -> Option<(&ExcerptId, BufferId, &BufferSnapshot)> {
2573        if self.singleton {
2574            self.excerpts
2575                .iter()
2576                .next()
2577                .map(|e| (&e.id, e.buffer_id, &e.buffer))
2578        } else {
2579            None
2580        }
2581    }
2582
2583    pub fn len(&self) -> usize {
2584        self.excerpts.summary().text.len
2585    }
2586
2587    pub fn is_empty(&self) -> bool {
2588        self.excerpts.summary().text.len == 0
2589    }
2590
2591    pub fn widest_line_number(&self) -> u32 {
2592        self.excerpts.summary().widest_line_number + 1
2593    }
2594
2595    pub fn clip_offset(&self, offset: usize, bias: Bias) -> usize {
2596        if let Some((_, _, buffer)) = self.as_singleton() {
2597            return buffer.clip_offset(offset, bias);
2598        }
2599
2600        let mut cursor = self.excerpts.cursor::<usize>(&());
2601        cursor.seek(&offset, Bias::Right, &());
2602        let overshoot = if let Some(excerpt) = cursor.item() {
2603            let excerpt_start = excerpt.range.context.start.to_offset(&excerpt.buffer);
2604            let buffer_offset = excerpt
2605                .buffer
2606                .clip_offset(excerpt_start + (offset - cursor.start()), bias);
2607            buffer_offset.saturating_sub(excerpt_start)
2608        } else {
2609            0
2610        };
2611        cursor.start() + overshoot
2612    }
2613
2614    pub fn clip_point(&self, point: Point, bias: Bias) -> Point {
2615        if let Some((_, _, buffer)) = self.as_singleton() {
2616            return buffer.clip_point(point, bias);
2617        }
2618
2619        let mut cursor = self.excerpts.cursor::<Point>(&());
2620        cursor.seek(&point, Bias::Right, &());
2621        let overshoot = if let Some(excerpt) = cursor.item() {
2622            let excerpt_start = excerpt.range.context.start.to_point(&excerpt.buffer);
2623            let buffer_point = excerpt
2624                .buffer
2625                .clip_point(excerpt_start + (point - cursor.start()), bias);
2626            buffer_point.saturating_sub(excerpt_start)
2627        } else {
2628            Point::zero()
2629        };
2630        *cursor.start() + overshoot
2631    }
2632
2633    pub fn clip_offset_utf16(&self, offset: OffsetUtf16, bias: Bias) -> OffsetUtf16 {
2634        if let Some((_, _, buffer)) = self.as_singleton() {
2635            return buffer.clip_offset_utf16(offset, bias);
2636        }
2637
2638        let mut cursor = self.excerpts.cursor::<OffsetUtf16>(&());
2639        cursor.seek(&offset, Bias::Right, &());
2640        let overshoot = if let Some(excerpt) = cursor.item() {
2641            let excerpt_start = excerpt.range.context.start.to_offset_utf16(&excerpt.buffer);
2642            let buffer_offset = excerpt
2643                .buffer
2644                .clip_offset_utf16(excerpt_start + (offset - cursor.start()), bias);
2645            OffsetUtf16(buffer_offset.0.saturating_sub(excerpt_start.0))
2646        } else {
2647            OffsetUtf16(0)
2648        };
2649        *cursor.start() + overshoot
2650    }
2651
2652    pub fn clip_point_utf16(&self, point: Unclipped<PointUtf16>, bias: Bias) -> PointUtf16 {
2653        if let Some((_, _, buffer)) = self.as_singleton() {
2654            return buffer.clip_point_utf16(point, bias);
2655        }
2656
2657        let mut cursor = self.excerpts.cursor::<PointUtf16>(&());
2658        cursor.seek(&point.0, Bias::Right, &());
2659        let overshoot = if let Some(excerpt) = cursor.item() {
2660            let excerpt_start = excerpt
2661                .buffer
2662                .offset_to_point_utf16(excerpt.range.context.start.to_offset(&excerpt.buffer));
2663            let buffer_point = excerpt
2664                .buffer
2665                .clip_point_utf16(Unclipped(excerpt_start + (point.0 - cursor.start())), bias);
2666            buffer_point.saturating_sub(excerpt_start)
2667        } else {
2668            PointUtf16::zero()
2669        };
2670        *cursor.start() + overshoot
2671    }
2672
2673    pub fn bytes_in_range<T: ToOffset>(&self, range: Range<T>) -> MultiBufferBytes {
2674        let range = range.start.to_offset(self)..range.end.to_offset(self);
2675        let mut excerpts = self.excerpts.cursor::<usize>(&());
2676        excerpts.seek(&range.start, Bias::Right, &());
2677
2678        let mut chunk = &[][..];
2679        let excerpt_bytes = if let Some(excerpt) = excerpts.item() {
2680            let mut excerpt_bytes = excerpt
2681                .bytes_in_range(range.start - excerpts.start()..range.end - excerpts.start());
2682            chunk = excerpt_bytes.next().unwrap_or(&[][..]);
2683            Some(excerpt_bytes)
2684        } else {
2685            None
2686        };
2687        MultiBufferBytes {
2688            range,
2689            excerpts,
2690            excerpt_bytes,
2691            chunk,
2692        }
2693    }
2694
2695    pub fn reversed_bytes_in_range<T: ToOffset>(
2696        &self,
2697        range: Range<T>,
2698    ) -> ReversedMultiBufferBytes {
2699        let range = range.start.to_offset(self)..range.end.to_offset(self);
2700        let mut excerpts = self.excerpts.cursor::<usize>(&());
2701        excerpts.seek(&range.end, Bias::Left, &());
2702
2703        let mut chunk = &[][..];
2704        let excerpt_bytes = if let Some(excerpt) = excerpts.item() {
2705            let mut excerpt_bytes = excerpt.reversed_bytes_in_range(
2706                range.start.saturating_sub(*excerpts.start())..range.end - *excerpts.start(),
2707            );
2708            chunk = excerpt_bytes.next().unwrap_or(&[][..]);
2709            Some(excerpt_bytes)
2710        } else {
2711            None
2712        };
2713
2714        ReversedMultiBufferBytes {
2715            range,
2716            excerpts,
2717            excerpt_bytes,
2718            chunk,
2719        }
2720    }
2721
2722    pub fn buffer_rows(&self, start_row: MultiBufferRow) -> MultiBufferRows {
2723        let mut result = MultiBufferRows {
2724            buffer_row_range: 0..0,
2725            excerpts: self.excerpts.cursor(&()),
2726        };
2727        result.seek(start_row);
2728        result
2729    }
2730
2731    pub fn chunks<T: ToOffset>(&self, range: Range<T>, language_aware: bool) -> MultiBufferChunks {
2732        let range = range.start.to_offset(self)..range.end.to_offset(self);
2733        let mut chunks = MultiBufferChunks {
2734            range: range.clone(),
2735            excerpts: self.excerpts.cursor(&()),
2736            excerpt_chunks: None,
2737            language_aware,
2738        };
2739        chunks.seek(range);
2740        chunks
2741    }
2742
2743    pub fn offset_to_point(&self, offset: usize) -> Point {
2744        if let Some((_, _, buffer)) = self.as_singleton() {
2745            return buffer.offset_to_point(offset);
2746        }
2747
2748        let mut cursor = self.excerpts.cursor::<(usize, Point)>(&());
2749        cursor.seek(&offset, Bias::Right, &());
2750        if let Some(excerpt) = cursor.item() {
2751            let (start_offset, start_point) = cursor.start();
2752            let overshoot = offset - start_offset;
2753            let excerpt_start_offset = excerpt.range.context.start.to_offset(&excerpt.buffer);
2754            let excerpt_start_point = excerpt.range.context.start.to_point(&excerpt.buffer);
2755            let buffer_point = excerpt
2756                .buffer
2757                .offset_to_point(excerpt_start_offset + overshoot);
2758            *start_point + (buffer_point - excerpt_start_point)
2759        } else {
2760            self.excerpts.summary().text.lines
2761        }
2762    }
2763
2764    pub fn offset_to_point_utf16(&self, offset: usize) -> PointUtf16 {
2765        if let Some((_, _, buffer)) = self.as_singleton() {
2766            return buffer.offset_to_point_utf16(offset);
2767        }
2768
2769        let mut cursor = self.excerpts.cursor::<(usize, PointUtf16)>(&());
2770        cursor.seek(&offset, Bias::Right, &());
2771        if let Some(excerpt) = cursor.item() {
2772            let (start_offset, start_point) = cursor.start();
2773            let overshoot = offset - start_offset;
2774            let excerpt_start_offset = excerpt.range.context.start.to_offset(&excerpt.buffer);
2775            let excerpt_start_point = excerpt.range.context.start.to_point_utf16(&excerpt.buffer);
2776            let buffer_point = excerpt
2777                .buffer
2778                .offset_to_point_utf16(excerpt_start_offset + overshoot);
2779            *start_point + (buffer_point - excerpt_start_point)
2780        } else {
2781            self.excerpts.summary().text.lines_utf16()
2782        }
2783    }
2784
2785    pub fn point_to_point_utf16(&self, point: Point) -> PointUtf16 {
2786        if let Some((_, _, buffer)) = self.as_singleton() {
2787            return buffer.point_to_point_utf16(point);
2788        }
2789
2790        let mut cursor = self.excerpts.cursor::<(Point, PointUtf16)>(&());
2791        cursor.seek(&point, Bias::Right, &());
2792        if let Some(excerpt) = cursor.item() {
2793            let (start_offset, start_point) = cursor.start();
2794            let overshoot = point - start_offset;
2795            let excerpt_start_point = excerpt.range.context.start.to_point(&excerpt.buffer);
2796            let excerpt_start_point_utf16 =
2797                excerpt.range.context.start.to_point_utf16(&excerpt.buffer);
2798            let buffer_point = excerpt
2799                .buffer
2800                .point_to_point_utf16(excerpt_start_point + overshoot);
2801            *start_point + (buffer_point - excerpt_start_point_utf16)
2802        } else {
2803            self.excerpts.summary().text.lines_utf16()
2804        }
2805    }
2806
2807    pub fn point_to_offset(&self, point: Point) -> usize {
2808        if let Some((_, _, buffer)) = self.as_singleton() {
2809            return buffer.point_to_offset(point);
2810        }
2811
2812        let mut cursor = self.excerpts.cursor::<(Point, usize)>(&());
2813        cursor.seek(&point, Bias::Right, &());
2814        if let Some(excerpt) = cursor.item() {
2815            let (start_point, start_offset) = cursor.start();
2816            let overshoot = point - start_point;
2817            let excerpt_start_offset = excerpt.range.context.start.to_offset(&excerpt.buffer);
2818            let excerpt_start_point = excerpt.range.context.start.to_point(&excerpt.buffer);
2819            let buffer_offset = excerpt
2820                .buffer
2821                .point_to_offset(excerpt_start_point + overshoot);
2822            *start_offset + buffer_offset - excerpt_start_offset
2823        } else {
2824            self.excerpts.summary().text.len
2825        }
2826    }
2827
2828    pub fn offset_utf16_to_offset(&self, offset_utf16: OffsetUtf16) -> usize {
2829        if let Some((_, _, buffer)) = self.as_singleton() {
2830            return buffer.offset_utf16_to_offset(offset_utf16);
2831        }
2832
2833        let mut cursor = self.excerpts.cursor::<(OffsetUtf16, usize)>(&());
2834        cursor.seek(&offset_utf16, Bias::Right, &());
2835        if let Some(excerpt) = cursor.item() {
2836            let (start_offset_utf16, start_offset) = cursor.start();
2837            let overshoot = offset_utf16 - start_offset_utf16;
2838            let excerpt_start_offset = excerpt.range.context.start.to_offset(&excerpt.buffer);
2839            let excerpt_start_offset_utf16 =
2840                excerpt.buffer.offset_to_offset_utf16(excerpt_start_offset);
2841            let buffer_offset = excerpt
2842                .buffer
2843                .offset_utf16_to_offset(excerpt_start_offset_utf16 + overshoot);
2844            *start_offset + (buffer_offset - excerpt_start_offset)
2845        } else {
2846            self.excerpts.summary().text.len
2847        }
2848    }
2849
2850    pub fn offset_to_offset_utf16(&self, offset: usize) -> OffsetUtf16 {
2851        if let Some((_, _, buffer)) = self.as_singleton() {
2852            return buffer.offset_to_offset_utf16(offset);
2853        }
2854
2855        let mut cursor = self.excerpts.cursor::<(usize, OffsetUtf16)>(&());
2856        cursor.seek(&offset, Bias::Right, &());
2857        if let Some(excerpt) = cursor.item() {
2858            let (start_offset, start_offset_utf16) = cursor.start();
2859            let overshoot = offset - start_offset;
2860            let excerpt_start_offset_utf16 =
2861                excerpt.range.context.start.to_offset_utf16(&excerpt.buffer);
2862            let excerpt_start_offset = excerpt
2863                .buffer
2864                .offset_utf16_to_offset(excerpt_start_offset_utf16);
2865            let buffer_offset_utf16 = excerpt
2866                .buffer
2867                .offset_to_offset_utf16(excerpt_start_offset + overshoot);
2868            *start_offset_utf16 + (buffer_offset_utf16 - excerpt_start_offset_utf16)
2869        } else {
2870            self.excerpts.summary().text.len_utf16
2871        }
2872    }
2873
2874    pub fn point_utf16_to_offset(&self, point: PointUtf16) -> usize {
2875        if let Some((_, _, buffer)) = self.as_singleton() {
2876            return buffer.point_utf16_to_offset(point);
2877        }
2878
2879        let mut cursor = self.excerpts.cursor::<(PointUtf16, usize)>(&());
2880        cursor.seek(&point, Bias::Right, &());
2881        if let Some(excerpt) = cursor.item() {
2882            let (start_point, start_offset) = cursor.start();
2883            let overshoot = point - start_point;
2884            let excerpt_start_offset = excerpt.range.context.start.to_offset(&excerpt.buffer);
2885            let excerpt_start_point = excerpt
2886                .buffer
2887                .offset_to_point_utf16(excerpt.range.context.start.to_offset(&excerpt.buffer));
2888            let buffer_offset = excerpt
2889                .buffer
2890                .point_utf16_to_offset(excerpt_start_point + overshoot);
2891            *start_offset + (buffer_offset - excerpt_start_offset)
2892        } else {
2893            self.excerpts.summary().text.len
2894        }
2895    }
2896
2897    pub fn point_to_buffer_offset<T: ToOffset>(
2898        &self,
2899        point: T,
2900    ) -> Option<(&BufferSnapshot, usize)> {
2901        let offset = point.to_offset(self);
2902        let mut cursor = self.excerpts.cursor::<usize>(&());
2903        cursor.seek(&offset, Bias::Right, &());
2904        if cursor.item().is_none() {
2905            cursor.prev(&());
2906        }
2907
2908        cursor.item().map(|excerpt| {
2909            let excerpt_start = excerpt.range.context.start.to_offset(&excerpt.buffer);
2910            let buffer_point = excerpt_start + offset - *cursor.start();
2911            (&excerpt.buffer, buffer_point)
2912        })
2913    }
2914
2915    pub fn suggested_indents(
2916        &self,
2917        rows: impl IntoIterator<Item = u32>,
2918        cx: &AppContext,
2919    ) -> BTreeMap<MultiBufferRow, IndentSize> {
2920        let mut result = BTreeMap::new();
2921
2922        let mut rows_for_excerpt = Vec::new();
2923        let mut cursor = self.excerpts.cursor::<Point>(&());
2924        let mut rows = rows.into_iter().peekable();
2925        let mut prev_row = u32::MAX;
2926        let mut prev_language_indent_size = IndentSize::default();
2927
2928        while let Some(row) = rows.next() {
2929            cursor.seek(&Point::new(row, 0), Bias::Right, &());
2930            let excerpt = match cursor.item() {
2931                Some(excerpt) => excerpt,
2932                _ => continue,
2933            };
2934
2935            // Retrieve the language and indent size once for each disjoint region being indented.
2936            let single_indent_size = if row.saturating_sub(1) == prev_row {
2937                prev_language_indent_size
2938            } else {
2939                excerpt
2940                    .buffer
2941                    .language_indent_size_at(Point::new(row, 0), cx)
2942            };
2943            prev_language_indent_size = single_indent_size;
2944            prev_row = row;
2945
2946            let start_buffer_row = excerpt.range.context.start.to_point(&excerpt.buffer).row;
2947            let start_multibuffer_row = cursor.start().row;
2948
2949            rows_for_excerpt.push(row);
2950            while let Some(next_row) = rows.peek().copied() {
2951                if cursor.end(&()).row > next_row {
2952                    rows_for_excerpt.push(next_row);
2953                    rows.next();
2954                } else {
2955                    break;
2956                }
2957            }
2958
2959            let buffer_rows = rows_for_excerpt
2960                .drain(..)
2961                .map(|row| start_buffer_row + row - start_multibuffer_row);
2962            let buffer_indents = excerpt
2963                .buffer
2964                .suggested_indents(buffer_rows, single_indent_size);
2965            let multibuffer_indents = buffer_indents.into_iter().map(|(row, indent)| {
2966                (
2967                    MultiBufferRow(start_multibuffer_row + row - start_buffer_row),
2968                    indent,
2969                )
2970            });
2971            result.extend(multibuffer_indents);
2972        }
2973
2974        result
2975    }
2976
2977    pub fn indent_size_for_line(&self, row: MultiBufferRow) -> IndentSize {
2978        if let Some((buffer, range)) = self.buffer_line_for_row(row) {
2979            let mut size = buffer.indent_size_for_line(range.start.row);
2980            size.len = size
2981                .len
2982                .min(range.end.column)
2983                .saturating_sub(range.start.column);
2984            size
2985        } else {
2986            IndentSize::spaces(0)
2987        }
2988    }
2989
2990    pub fn indent_and_comment_for_line(&self, row: MultiBufferRow, cx: &AppContext) -> String {
2991        let mut indent = self.indent_size_for_line(row).chars().collect::<String>();
2992
2993        if self.settings_at(0, cx).extend_comment_on_newline {
2994            if let Some(language_scope) = self.language_scope_at(Point::new(row.0, 0)) {
2995                let delimiters = language_scope.line_comment_prefixes();
2996                for delimiter in delimiters {
2997                    if *self
2998                        .chars_at(Point::new(row.0, indent.len() as u32))
2999                        .take(delimiter.chars().count())
3000                        .collect::<String>()
3001                        .as_str()
3002                        == **delimiter
3003                    {
3004                        indent.push_str(&delimiter);
3005                        break;
3006                    }
3007                }
3008            }
3009        }
3010
3011        indent
3012    }
3013
3014    pub fn prev_non_blank_row(&self, mut row: MultiBufferRow) -> Option<MultiBufferRow> {
3015        while row.0 > 0 {
3016            row.0 -= 1;
3017            if !self.is_line_blank(row) {
3018                return Some(row);
3019            }
3020        }
3021        None
3022    }
3023
3024    pub fn line_len(&self, row: MultiBufferRow) -> u32 {
3025        if let Some((_, range)) = self.buffer_line_for_row(row) {
3026            range.end.column - range.start.column
3027        } else {
3028            0
3029        }
3030    }
3031
3032    pub fn buffer_line_for_row(
3033        &self,
3034        row: MultiBufferRow,
3035    ) -> Option<(&BufferSnapshot, Range<Point>)> {
3036        let mut cursor = self.excerpts.cursor::<Point>(&());
3037        let point = Point::new(row.0, 0);
3038        cursor.seek(&point, Bias::Right, &());
3039        if cursor.item().is_none() && *cursor.start() == point {
3040            cursor.prev(&());
3041        }
3042        if let Some(excerpt) = cursor.item() {
3043            let overshoot = row.0 - cursor.start().row;
3044            let excerpt_start = excerpt.range.context.start.to_point(&excerpt.buffer);
3045            let excerpt_end = excerpt.range.context.end.to_point(&excerpt.buffer);
3046            let buffer_row = excerpt_start.row + overshoot;
3047            let line_start = Point::new(buffer_row, 0);
3048            let line_end = Point::new(buffer_row, excerpt.buffer.line_len(buffer_row));
3049            return Some((
3050                &excerpt.buffer,
3051                line_start.max(excerpt_start)..line_end.min(excerpt_end),
3052            ));
3053        }
3054        None
3055    }
3056
3057    pub fn max_point(&self) -> Point {
3058        self.text_summary().lines
3059    }
3060
3061    pub fn max_row(&self) -> MultiBufferRow {
3062        MultiBufferRow(self.text_summary().lines.row)
3063    }
3064
3065    pub fn text_summary(&self) -> TextSummary {
3066        self.excerpts.summary().text.clone()
3067    }
3068
3069    pub fn text_summary_for_range<D, O>(&self, range: Range<O>) -> D
3070    where
3071        D: TextDimension,
3072        O: ToOffset,
3073    {
3074        let mut summary = D::zero(&());
3075        let mut range = range.start.to_offset(self)..range.end.to_offset(self);
3076        let mut cursor = self.excerpts.cursor::<usize>(&());
3077        cursor.seek(&range.start, Bias::Right, &());
3078        if let Some(excerpt) = cursor.item() {
3079            let mut end_before_newline = cursor.end(&());
3080            if excerpt.has_trailing_newline {
3081                end_before_newline -= 1;
3082            }
3083
3084            let excerpt_start = excerpt.range.context.start.to_offset(&excerpt.buffer);
3085            let start_in_excerpt = excerpt_start + (range.start - cursor.start());
3086            let end_in_excerpt =
3087                excerpt_start + (cmp::min(end_before_newline, range.end) - cursor.start());
3088            summary.add_assign(
3089                &excerpt
3090                    .buffer
3091                    .text_summary_for_range(start_in_excerpt..end_in_excerpt),
3092            );
3093
3094            if range.end > end_before_newline {
3095                summary.add_assign(&D::from_text_summary(&TextSummary::from("\n")));
3096            }
3097
3098            cursor.next(&());
3099        }
3100
3101        if range.end > *cursor.start() {
3102            summary.add_assign(&D::from_text_summary(&cursor.summary::<_, TextSummary>(
3103                &range.end,
3104                Bias::Right,
3105                &(),
3106            )));
3107            if let Some(excerpt) = cursor.item() {
3108                range.end = cmp::max(*cursor.start(), range.end);
3109
3110                let excerpt_start = excerpt.range.context.start.to_offset(&excerpt.buffer);
3111                let end_in_excerpt = excerpt_start + (range.end - cursor.start());
3112                summary.add_assign(
3113                    &excerpt
3114                        .buffer
3115                        .text_summary_for_range(excerpt_start..end_in_excerpt),
3116                );
3117            }
3118        }
3119
3120        summary
3121    }
3122
3123    pub fn summary_for_anchor<D>(&self, anchor: &Anchor) -> D
3124    where
3125        D: TextDimension + Ord + Sub<D, Output = D>,
3126    {
3127        let mut cursor = self.excerpts.cursor::<ExcerptSummary>(&());
3128        let locator = self.excerpt_locator_for_id(anchor.excerpt_id);
3129
3130        cursor.seek(locator, Bias::Left, &());
3131        if cursor.item().is_none() {
3132            cursor.next(&());
3133        }
3134
3135        let mut position = D::from_text_summary(&cursor.start().text);
3136        if let Some(excerpt) = cursor.item() {
3137            if excerpt.id == anchor.excerpt_id {
3138                let excerpt_buffer_start =
3139                    excerpt.range.context.start.summary::<D>(&excerpt.buffer);
3140                let excerpt_buffer_end = excerpt.range.context.end.summary::<D>(&excerpt.buffer);
3141                let buffer_position = cmp::min(
3142                    excerpt_buffer_end,
3143                    anchor.text_anchor.summary::<D>(&excerpt.buffer),
3144                );
3145                if buffer_position > excerpt_buffer_start {
3146                    position.add_assign(&(buffer_position - excerpt_buffer_start));
3147                }
3148            }
3149        }
3150        position
3151    }
3152
3153    pub fn summaries_for_anchors<'a, D, I>(&'a self, anchors: I) -> Vec<D>
3154    where
3155        D: TextDimension + Ord + Sub<D, Output = D>,
3156        I: 'a + IntoIterator<Item = &'a Anchor>,
3157    {
3158        if let Some((_, _, buffer)) = self.as_singleton() {
3159            return buffer
3160                .summaries_for_anchors(anchors.into_iter().map(|a| &a.text_anchor))
3161                .collect();
3162        }
3163
3164        let mut anchors = anchors.into_iter().peekable();
3165        let mut cursor = self.excerpts.cursor::<ExcerptSummary>(&());
3166        let mut summaries = Vec::new();
3167        while let Some(anchor) = anchors.peek() {
3168            let excerpt_id = anchor.excerpt_id;
3169            let excerpt_anchors = iter::from_fn(|| {
3170                let anchor = anchors.peek()?;
3171                if anchor.excerpt_id == excerpt_id {
3172                    Some(&anchors.next().unwrap().text_anchor)
3173                } else {
3174                    None
3175                }
3176            });
3177
3178            let locator = self.excerpt_locator_for_id(excerpt_id);
3179            cursor.seek_forward(locator, Bias::Left, &());
3180            if cursor.item().is_none() {
3181                cursor.next(&());
3182            }
3183
3184            let position = D::from_text_summary(&cursor.start().text);
3185            if let Some(excerpt) = cursor.item() {
3186                if excerpt.id == excerpt_id {
3187                    let excerpt_buffer_start =
3188                        excerpt.range.context.start.summary::<D>(&excerpt.buffer);
3189                    let excerpt_buffer_end =
3190                        excerpt.range.context.end.summary::<D>(&excerpt.buffer);
3191                    summaries.extend(
3192                        excerpt
3193                            .buffer
3194                            .summaries_for_anchors::<D, _>(excerpt_anchors)
3195                            .map(move |summary| {
3196                                let summary = cmp::min(excerpt_buffer_end.clone(), summary);
3197                                let mut position = position.clone();
3198                                let excerpt_buffer_start = excerpt_buffer_start.clone();
3199                                if summary > excerpt_buffer_start {
3200                                    position.add_assign(&(summary - excerpt_buffer_start));
3201                                }
3202                                position
3203                            }),
3204                    );
3205                    continue;
3206                }
3207            }
3208
3209            summaries.extend(excerpt_anchors.map(|_| position.clone()));
3210        }
3211
3212        summaries
3213    }
3214
3215    pub fn dimensions_from_points<'a, D>(
3216        &'a self,
3217        points: impl 'a + IntoIterator<Item = Point>,
3218    ) -> impl 'a + Iterator<Item = D>
3219    where
3220        D: TextDimension,
3221    {
3222        let mut cursor = self.excerpts.cursor::<TextSummary>(&());
3223        let mut memoized_source_start: Option<Point> = None;
3224        let mut points = points.into_iter();
3225        std::iter::from_fn(move || {
3226            let point = points.next()?;
3227
3228            // Clear the memoized source start if the point is in a different excerpt than previous.
3229            if memoized_source_start.map_or(false, |_| point >= cursor.end(&()).lines) {
3230                memoized_source_start = None;
3231            }
3232
3233            // Now determine where the excerpt containing the point starts in its source buffer.
3234            // We'll use this value to calculate overshoot next.
3235            let source_start = if let Some(source_start) = memoized_source_start {
3236                source_start
3237            } else {
3238                cursor.seek_forward(&point, Bias::Right, &());
3239                if let Some(excerpt) = cursor.item() {
3240                    let source_start = excerpt.range.context.start.to_point(&excerpt.buffer);
3241                    memoized_source_start = Some(source_start);
3242                    source_start
3243                } else {
3244                    return Some(D::from_text_summary(cursor.start()));
3245                }
3246            };
3247
3248            // First, assume the output dimension is at least the start of the excerpt containing the point
3249            let mut output = D::from_text_summary(cursor.start());
3250
3251            // If the point lands within its excerpt, calculate and add the overshoot in dimension D.
3252            if let Some(excerpt) = cursor.item() {
3253                let overshoot = point - cursor.start().lines;
3254                if !overshoot.is_zero() {
3255                    let end_in_excerpt = source_start + overshoot;
3256                    output.add_assign(
3257                        &excerpt
3258                            .buffer
3259                            .text_summary_for_range::<D, _>(source_start..end_in_excerpt),
3260                    );
3261                }
3262            }
3263            Some(output)
3264        })
3265    }
3266
3267    pub fn refresh_anchors<'a, I>(&'a self, anchors: I) -> Vec<(usize, Anchor, bool)>
3268    where
3269        I: 'a + IntoIterator<Item = &'a Anchor>,
3270    {
3271        let mut anchors = anchors.into_iter().enumerate().peekable();
3272        let mut cursor = self.excerpts.cursor::<Option<&Locator>>(&());
3273        cursor.next(&());
3274
3275        let mut result = Vec::new();
3276
3277        while let Some((_, anchor)) = anchors.peek() {
3278            let old_excerpt_id = anchor.excerpt_id;
3279
3280            // Find the location where this anchor's excerpt should be.
3281            let old_locator = self.excerpt_locator_for_id(old_excerpt_id);
3282            cursor.seek_forward(&Some(old_locator), Bias::Left, &());
3283
3284            if cursor.item().is_none() {
3285                cursor.next(&());
3286            }
3287
3288            let next_excerpt = cursor.item();
3289            let prev_excerpt = cursor.prev_item();
3290
3291            // Process all of the anchors for this excerpt.
3292            while let Some((_, anchor)) = anchors.peek() {
3293                if anchor.excerpt_id != old_excerpt_id {
3294                    break;
3295                }
3296                let (anchor_ix, anchor) = anchors.next().unwrap();
3297                let mut anchor = *anchor;
3298
3299                // Leave min and max anchors unchanged if invalid or
3300                // if the old excerpt still exists at this location
3301                let mut kept_position = next_excerpt
3302                    .map_or(false, |e| e.id == old_excerpt_id && e.contains(&anchor))
3303                    || old_excerpt_id == ExcerptId::max()
3304                    || old_excerpt_id == ExcerptId::min();
3305
3306                // If the old excerpt no longer exists at this location, then attempt to
3307                // find an equivalent position for this anchor in an adjacent excerpt.
3308                if !kept_position {
3309                    for excerpt in [next_excerpt, prev_excerpt].iter().filter_map(|e| *e) {
3310                        if excerpt.contains(&anchor) {
3311                            anchor.excerpt_id = excerpt.id;
3312                            kept_position = true;
3313                            break;
3314                        }
3315                    }
3316                }
3317
3318                // If there's no adjacent excerpt that contains the anchor's position,
3319                // then report that the anchor has lost its position.
3320                if !kept_position {
3321                    anchor = if let Some(excerpt) = next_excerpt {
3322                        let mut text_anchor = excerpt
3323                            .range
3324                            .context
3325                            .start
3326                            .bias(anchor.text_anchor.bias, &excerpt.buffer);
3327                        if text_anchor
3328                            .cmp(&excerpt.range.context.end, &excerpt.buffer)
3329                            .is_gt()
3330                        {
3331                            text_anchor = excerpt.range.context.end;
3332                        }
3333                        Anchor {
3334                            buffer_id: Some(excerpt.buffer_id),
3335                            excerpt_id: excerpt.id,
3336                            text_anchor,
3337                        }
3338                    } else if let Some(excerpt) = prev_excerpt {
3339                        let mut text_anchor = excerpt
3340                            .range
3341                            .context
3342                            .end
3343                            .bias(anchor.text_anchor.bias, &excerpt.buffer);
3344                        if text_anchor
3345                            .cmp(&excerpt.range.context.start, &excerpt.buffer)
3346                            .is_lt()
3347                        {
3348                            text_anchor = excerpt.range.context.start;
3349                        }
3350                        Anchor {
3351                            buffer_id: Some(excerpt.buffer_id),
3352                            excerpt_id: excerpt.id,
3353                            text_anchor,
3354                        }
3355                    } else if anchor.text_anchor.bias == Bias::Left {
3356                        Anchor::min()
3357                    } else {
3358                        Anchor::max()
3359                    };
3360                }
3361
3362                result.push((anchor_ix, anchor, kept_position));
3363            }
3364        }
3365        result.sort_unstable_by(|a, b| a.1.cmp(&b.1, self));
3366        result
3367    }
3368
3369    pub fn anchor_before<T: ToOffset>(&self, position: T) -> Anchor {
3370        self.anchor_at(position, Bias::Left)
3371    }
3372
3373    pub fn anchor_after<T: ToOffset>(&self, position: T) -> Anchor {
3374        self.anchor_at(position, Bias::Right)
3375    }
3376
3377    pub fn anchor_at<T: ToOffset>(&self, position: T, mut bias: Bias) -> Anchor {
3378        let offset = position.to_offset(self);
3379        if let Some((excerpt_id, buffer_id, buffer)) = self.as_singleton() {
3380            return Anchor {
3381                buffer_id: Some(buffer_id),
3382                excerpt_id: *excerpt_id,
3383                text_anchor: buffer.anchor_at(offset, bias),
3384            };
3385        }
3386
3387        let mut cursor = self.excerpts.cursor::<(usize, Option<ExcerptId>)>(&());
3388        cursor.seek(&offset, Bias::Right, &());
3389        if cursor.item().is_none() && offset == cursor.start().0 && bias == Bias::Left {
3390            cursor.prev(&());
3391        }
3392        if let Some(excerpt) = cursor.item() {
3393            let mut overshoot = offset.saturating_sub(cursor.start().0);
3394            if excerpt.has_trailing_newline && offset == cursor.end(&()).0 {
3395                overshoot -= 1;
3396                bias = Bias::Right;
3397            }
3398
3399            let buffer_start = excerpt.range.context.start.to_offset(&excerpt.buffer);
3400            let text_anchor =
3401                excerpt.clip_anchor(excerpt.buffer.anchor_at(buffer_start + overshoot, bias));
3402            Anchor {
3403                buffer_id: Some(excerpt.buffer_id),
3404                excerpt_id: excerpt.id,
3405                text_anchor,
3406            }
3407        } else if offset == 0 && bias == Bias::Left {
3408            Anchor::min()
3409        } else {
3410            Anchor::max()
3411        }
3412    }
3413
3414    /// Returns an anchor for the given excerpt and text anchor,
3415    /// returns None if the excerpt_id is no longer valid.
3416    pub fn anchor_in_excerpt(
3417        &self,
3418        excerpt_id: ExcerptId,
3419        text_anchor: text::Anchor,
3420    ) -> Option<Anchor> {
3421        let locator = self.excerpt_locator_for_id(excerpt_id);
3422        let mut cursor = self.excerpts.cursor::<Option<&Locator>>(&());
3423        cursor.seek(locator, Bias::Left, &());
3424        if let Some(excerpt) = cursor.item() {
3425            if excerpt.id == excerpt_id {
3426                let text_anchor = excerpt.clip_anchor(text_anchor);
3427                drop(cursor);
3428                return Some(Anchor {
3429                    buffer_id: Some(excerpt.buffer_id),
3430                    excerpt_id,
3431                    text_anchor,
3432                });
3433            }
3434        }
3435        None
3436    }
3437
3438    pub fn context_range_for_excerpt(&self, excerpt_id: ExcerptId) -> Option<Range<text::Anchor>> {
3439        Some(self.excerpt(excerpt_id)?.range.context.clone())
3440    }
3441
3442    pub fn can_resolve(&self, anchor: &Anchor) -> bool {
3443        if anchor.excerpt_id == ExcerptId::min() || anchor.excerpt_id == ExcerptId::max() {
3444            true
3445        } else if let Some(excerpt) = self.excerpt(anchor.excerpt_id) {
3446            excerpt.buffer.can_resolve(&anchor.text_anchor)
3447        } else {
3448            false
3449        }
3450    }
3451
3452    pub fn buffer_ids_in_selected_rows(
3453        &self,
3454        selection: Selection<Point>,
3455    ) -> impl Iterator<Item = BufferId> + '_ {
3456        let mut cursor = self.excerpts.cursor::<Point>(&());
3457        cursor.seek(&Point::new(selection.start.row, 0), Bias::Right, &());
3458        cursor.prev(&());
3459
3460        iter::from_fn(move || {
3461            cursor.next(&());
3462            if cursor.start().row <= selection.end.row {
3463                cursor.item().map(|item| item.buffer_id)
3464            } else {
3465                None
3466            }
3467        })
3468    }
3469
3470    pub fn excerpts(
3471        &self,
3472    ) -> impl Iterator<Item = (ExcerptId, &BufferSnapshot, ExcerptRange<text::Anchor>)> {
3473        self.excerpts
3474            .iter()
3475            .map(|excerpt| (excerpt.id, &excerpt.buffer, excerpt.range.clone()))
3476    }
3477
3478    pub fn all_excerpts(&self) -> impl Iterator<Item = MultiBufferExcerpt> {
3479        let mut cursor = self.excerpts.cursor::<(usize, Point)>(&());
3480        cursor.next(&());
3481        std::iter::from_fn(move || {
3482            let excerpt = cursor.item()?;
3483            let excerpt = MultiBufferExcerpt::new(excerpt, *cursor.start());
3484            cursor.next(&());
3485            Some(excerpt)
3486        })
3487    }
3488
3489    pub fn excerpts_for_range<T: ToOffset>(
3490        &self,
3491        range: Range<T>,
3492    ) -> impl Iterator<Item = MultiBufferExcerpt> + '_ {
3493        let range = range.start.to_offset(self)..range.end.to_offset(self);
3494
3495        let mut cursor = self.excerpts.cursor::<(usize, Point)>(&());
3496        cursor.seek(&range.start, Bias::Right, &());
3497        cursor.prev(&());
3498
3499        iter::from_fn(move || {
3500            cursor.next(&());
3501            if cursor.start().0 < range.end {
3502                cursor
3503                    .item()
3504                    .map(|item| MultiBufferExcerpt::new(item, *cursor.start()))
3505            } else {
3506                None
3507            }
3508        })
3509    }
3510
3511    pub fn excerpts_for_range_rev<T: ToOffset>(
3512        &self,
3513        range: Range<T>,
3514    ) -> impl Iterator<Item = MultiBufferExcerpt> + '_ {
3515        let range = range.start.to_offset(self)..range.end.to_offset(self);
3516
3517        let mut cursor = self.excerpts.cursor::<(usize, Point)>(&());
3518        cursor.seek(&range.end, Bias::Left, &());
3519        if cursor.item().is_none() {
3520            cursor.prev(&());
3521        }
3522
3523        std::iter::from_fn(move || {
3524            let excerpt = cursor.item()?;
3525            let excerpt = MultiBufferExcerpt::new(excerpt, *cursor.start());
3526            cursor.prev(&());
3527            Some(excerpt)
3528        })
3529    }
3530
3531    pub fn excerpt_before(&self, id: ExcerptId) -> Option<MultiBufferExcerpt<'_>> {
3532        let start_locator = self.excerpt_locator_for_id(id);
3533        let mut cursor = self.excerpts.cursor::<ExcerptSummary>(&());
3534        cursor.seek(start_locator, Bias::Left, &());
3535        cursor.prev(&());
3536        let excerpt = cursor.item()?;
3537        let excerpt_offset = cursor.start().text.len;
3538        let excerpt_position = cursor.start().text.lines;
3539        Some(MultiBufferExcerpt {
3540            excerpt,
3541            excerpt_offset,
3542            excerpt_position,
3543        })
3544    }
3545
3546    pub fn excerpt_after(&self, id: ExcerptId) -> Option<MultiBufferExcerpt<'_>> {
3547        let start_locator = self.excerpt_locator_for_id(id);
3548        let mut cursor = self.excerpts.cursor::<ExcerptSummary>(&());
3549        cursor.seek(start_locator, Bias::Left, &());
3550        cursor.next(&());
3551        let excerpt = cursor.item()?;
3552        let excerpt_offset = cursor.start().text.len;
3553        let excerpt_position = cursor.start().text.lines;
3554        Some(MultiBufferExcerpt {
3555            excerpt,
3556            excerpt_offset,
3557            excerpt_position,
3558        })
3559    }
3560
3561    pub fn excerpt_boundaries_in_range<R, T>(
3562        &self,
3563        range: R,
3564    ) -> impl Iterator<Item = ExcerptBoundary> + '_
3565    where
3566        R: RangeBounds<T>,
3567        T: ToOffset,
3568    {
3569        let start_offset;
3570        let start = match range.start_bound() {
3571            Bound::Included(start) => {
3572                start_offset = start.to_offset(self);
3573                Bound::Included(start_offset)
3574            }
3575            Bound::Excluded(start) => {
3576                start_offset = start.to_offset(self);
3577                Bound::Excluded(start_offset)
3578            }
3579            Bound::Unbounded => {
3580                start_offset = 0;
3581                Bound::Unbounded
3582            }
3583        };
3584        let end = match range.end_bound() {
3585            Bound::Included(end) => Bound::Included(end.to_offset(self)),
3586            Bound::Excluded(end) => Bound::Excluded(end.to_offset(self)),
3587            Bound::Unbounded => Bound::Unbounded,
3588        };
3589        let bounds = (start, end);
3590
3591        let mut cursor = self.excerpts.cursor::<(usize, Point)>(&());
3592        cursor.seek(&start_offset, Bias::Right, &());
3593        if cursor.item().is_none() {
3594            cursor.prev(&());
3595        }
3596        if !bounds.contains(&cursor.start().0) {
3597            cursor.next(&());
3598        }
3599
3600        let mut visited_end = false;
3601        std::iter::from_fn(move || {
3602            if self.singleton {
3603                None
3604            } else if bounds.contains(&cursor.start().0) {
3605                let next = cursor.item().map(|excerpt| ExcerptInfo {
3606                    id: excerpt.id,
3607                    buffer: excerpt.buffer.clone(),
3608                    buffer_id: excerpt.buffer_id,
3609                    range: excerpt.range.clone(),
3610                    text_summary: excerpt.text_summary.clone(),
3611                });
3612
3613                if next.is_none() {
3614                    if visited_end {
3615                        return None;
3616                    } else {
3617                        visited_end = true;
3618                    }
3619                }
3620
3621                let prev = cursor.prev_item().map(|prev_excerpt| ExcerptInfo {
3622                    id: prev_excerpt.id,
3623                    buffer: prev_excerpt.buffer.clone(),
3624                    buffer_id: prev_excerpt.buffer_id,
3625                    range: prev_excerpt.range.clone(),
3626                    text_summary: prev_excerpt.text_summary.clone(),
3627                });
3628                let row = MultiBufferRow(cursor.start().1.row);
3629
3630                cursor.next(&());
3631
3632                Some(ExcerptBoundary { row, prev, next })
3633            } else {
3634                None
3635            }
3636        })
3637    }
3638
3639    pub fn edit_count(&self) -> usize {
3640        self.edit_count
3641    }
3642
3643    pub fn non_text_state_update_count(&self) -> usize {
3644        self.non_text_state_update_count
3645    }
3646
3647    /// Returns the smallest enclosing bracket ranges containing the given range or
3648    /// None if no brackets contain range or the range is not contained in a single
3649    /// excerpt
3650    ///
3651    /// Can optionally pass a range_filter to filter the ranges of brackets to consider
3652    pub fn innermost_enclosing_bracket_ranges<T: ToOffset>(
3653        &self,
3654        range: Range<T>,
3655        range_filter: Option<&dyn Fn(Range<usize>, Range<usize>) -> bool>,
3656    ) -> Option<(Range<usize>, Range<usize>)> {
3657        let range = range.start.to_offset(self)..range.end.to_offset(self);
3658        let excerpt = self.excerpt_containing(range.clone())?;
3659
3660        // Filter to ranges contained in the excerpt
3661        let range_filter = |open: Range<usize>, close: Range<usize>| -> bool {
3662            excerpt.contains_buffer_range(open.start..close.end)
3663                && range_filter.map_or(true, |filter| {
3664                    filter(
3665                        excerpt.map_range_from_buffer(open),
3666                        excerpt.map_range_from_buffer(close),
3667                    )
3668                })
3669        };
3670
3671        let (open, close) = excerpt.buffer().innermost_enclosing_bracket_ranges(
3672            excerpt.map_range_to_buffer(range),
3673            Some(&range_filter),
3674        )?;
3675
3676        Some((
3677            excerpt.map_range_from_buffer(open),
3678            excerpt.map_range_from_buffer(close),
3679        ))
3680    }
3681
3682    /// Returns enclosing bracket ranges containing the given range or returns None if the range is
3683    /// not contained in a single excerpt
3684    pub fn enclosing_bracket_ranges<T: ToOffset>(
3685        &self,
3686        range: Range<T>,
3687    ) -> Option<impl Iterator<Item = (Range<usize>, Range<usize>)> + '_> {
3688        let range = range.start.to_offset(self)..range.end.to_offset(self);
3689        let excerpt = self.excerpt_containing(range.clone())?;
3690
3691        Some(
3692            excerpt
3693                .buffer()
3694                .enclosing_bracket_ranges(excerpt.map_range_to_buffer(range))
3695                .filter_map(move |(open, close)| {
3696                    if excerpt.contains_buffer_range(open.start..close.end) {
3697                        Some((
3698                            excerpt.map_range_from_buffer(open),
3699                            excerpt.map_range_from_buffer(close),
3700                        ))
3701                    } else {
3702                        None
3703                    }
3704                }),
3705        )
3706    }
3707
3708    /// Returns bracket range pairs overlapping the given `range` or returns None if the `range` is
3709    /// not contained in a single excerpt
3710    pub fn bracket_ranges<T: ToOffset>(
3711        &self,
3712        range: Range<T>,
3713    ) -> Option<impl Iterator<Item = (Range<usize>, Range<usize>)> + '_> {
3714        let range = range.start.to_offset(self)..range.end.to_offset(self);
3715        let excerpt = self.excerpt_containing(range.clone())?;
3716
3717        Some(
3718            excerpt
3719                .buffer()
3720                .bracket_ranges(excerpt.map_range_to_buffer(range))
3721                .filter_map(move |(start_bracket_range, close_bracket_range)| {
3722                    let buffer_range = start_bracket_range.start..close_bracket_range.end;
3723                    if excerpt.contains_buffer_range(buffer_range) {
3724                        Some((
3725                            excerpt.map_range_from_buffer(start_bracket_range),
3726                            excerpt.map_range_from_buffer(close_bracket_range),
3727                        ))
3728                    } else {
3729                        None
3730                    }
3731                }),
3732        )
3733    }
3734
3735    pub fn redacted_ranges<'a, T: ToOffset>(
3736        &'a self,
3737        range: Range<T>,
3738        redaction_enabled: impl Fn(Option<&Arc<dyn File>>) -> bool + 'a,
3739    ) -> impl Iterator<Item = Range<usize>> + 'a {
3740        let range = range.start.to_offset(self)..range.end.to_offset(self);
3741        self.excerpts_for_range(range.clone())
3742            .filter(move |excerpt| redaction_enabled(excerpt.buffer().file()))
3743            .flat_map(move |excerpt| {
3744                excerpt
3745                    .buffer()
3746                    .redacted_ranges(excerpt.buffer_range().clone())
3747                    .map(move |redacted_range| excerpt.map_range_from_buffer(redacted_range))
3748                    .skip_while(move |redacted_range| redacted_range.end < range.start)
3749                    .take_while(move |redacted_range| redacted_range.start < range.end)
3750            })
3751    }
3752
3753    pub fn runnable_ranges(
3754        &self,
3755        range: Range<Anchor>,
3756    ) -> impl Iterator<Item = language::RunnableRange> + '_ {
3757        let range = range.start.to_offset(self)..range.end.to_offset(self);
3758        self.excerpts_for_range(range.clone())
3759            .flat_map(move |excerpt| {
3760                let excerpt_buffer_start =
3761                    excerpt.buffer_range().start.to_offset(&excerpt.buffer());
3762
3763                excerpt
3764                    .buffer()
3765                    .runnable_ranges(excerpt.buffer_range())
3766                    .filter_map(move |mut runnable| {
3767                        // Re-base onto the excerpts coordinates in the multibuffer
3768                        //
3769                        // The node matching our runnables query might partially overlap with
3770                        // the provided range. If the run indicator is outside of excerpt bounds, do not actually show it.
3771                        if runnable.run_range.start < excerpt_buffer_start {
3772                            return None;
3773                        }
3774                        if language::ToPoint::to_point(&runnable.run_range.end, &excerpt.buffer())
3775                            .row
3776                            > excerpt.max_buffer_row()
3777                        {
3778                            return None;
3779                        }
3780                        runnable.run_range = excerpt.map_range_from_buffer(runnable.run_range);
3781
3782                        Some(runnable)
3783                    })
3784                    .skip_while(move |runnable| runnable.run_range.end < range.start)
3785                    .take_while(move |runnable| runnable.run_range.start < range.end)
3786            })
3787    }
3788
3789    pub fn indent_guides_in_range(
3790        &self,
3791        range: Range<Anchor>,
3792        ignore_disabled_for_language: bool,
3793        cx: &AppContext,
3794    ) -> Vec<MultiBufferIndentGuide> {
3795        // Fast path for singleton buffers, we can skip the conversion between offsets.
3796        if let Some((_, _, snapshot)) = self.as_singleton() {
3797            return snapshot
3798                .indent_guides_in_range(
3799                    range.start.text_anchor..range.end.text_anchor,
3800                    ignore_disabled_for_language,
3801                    cx,
3802                )
3803                .into_iter()
3804                .map(|guide| MultiBufferIndentGuide {
3805                    multibuffer_row_range: MultiBufferRow(guide.start_row)
3806                        ..MultiBufferRow(guide.end_row),
3807                    buffer: guide,
3808                })
3809                .collect();
3810        }
3811
3812        let range = range.start.to_offset(self)..range.end.to_offset(self);
3813
3814        self.excerpts_for_range(range.clone())
3815            .flat_map(move |excerpt| {
3816                let excerpt_buffer_start_row =
3817                    excerpt.buffer_range().start.to_point(&excerpt.buffer()).row;
3818                let excerpt_offset_row = excerpt.start_point().row;
3819
3820                excerpt
3821                    .buffer()
3822                    .indent_guides_in_range(
3823                        excerpt.buffer_range(),
3824                        ignore_disabled_for_language,
3825                        cx,
3826                    )
3827                    .into_iter()
3828                    .map(move |indent_guide| {
3829                        let start_row = excerpt_offset_row
3830                            + (indent_guide.start_row - excerpt_buffer_start_row);
3831                        let end_row =
3832                            excerpt_offset_row + (indent_guide.end_row - excerpt_buffer_start_row);
3833
3834                        MultiBufferIndentGuide {
3835                            multibuffer_row_range: MultiBufferRow(start_row)
3836                                ..MultiBufferRow(end_row),
3837                            buffer: indent_guide,
3838                        }
3839                    })
3840            })
3841            .collect()
3842    }
3843
3844    pub fn trailing_excerpt_update_count(&self) -> usize {
3845        self.trailing_excerpt_update_count
3846    }
3847
3848    pub fn file_at<T: ToOffset>(&self, point: T) -> Option<&Arc<dyn File>> {
3849        self.point_to_buffer_offset(point)
3850            .and_then(|(buffer, _)| buffer.file())
3851    }
3852
3853    pub fn language_at<T: ToOffset>(&self, point: T) -> Option<&Arc<Language>> {
3854        self.point_to_buffer_offset(point)
3855            .and_then(|(buffer, offset)| buffer.language_at(offset))
3856    }
3857
3858    pub fn settings_at<'a, T: ToOffset>(
3859        &'a self,
3860        point: T,
3861        cx: &'a AppContext,
3862    ) -> Cow<'a, LanguageSettings> {
3863        let mut language = None;
3864        let mut file = None;
3865        if let Some((buffer, offset)) = self.point_to_buffer_offset(point) {
3866            language = buffer.language_at(offset);
3867            file = buffer.file();
3868        }
3869        language_settings(language.map(|l| l.name()), file, cx)
3870    }
3871
3872    pub fn language_scope_at<T: ToOffset>(&self, point: T) -> Option<LanguageScope> {
3873        self.point_to_buffer_offset(point)
3874            .and_then(|(buffer, offset)| buffer.language_scope_at(offset))
3875    }
3876
3877    pub fn char_classifier_at<T: ToOffset>(&self, point: T) -> CharClassifier {
3878        self.point_to_buffer_offset(point)
3879            .map(|(buffer, offset)| buffer.char_classifier_at(offset))
3880            .unwrap_or_default()
3881    }
3882
3883    pub fn language_indent_size_at<T: ToOffset>(
3884        &self,
3885        position: T,
3886        cx: &AppContext,
3887    ) -> Option<IndentSize> {
3888        let (buffer_snapshot, offset) = self.point_to_buffer_offset(position)?;
3889        Some(buffer_snapshot.language_indent_size_at(offset, cx))
3890    }
3891
3892    pub fn is_dirty(&self) -> bool {
3893        self.is_dirty
3894    }
3895
3896    pub fn has_deleted_file(&self) -> bool {
3897        self.has_deleted_file
3898    }
3899
3900    pub fn has_conflict(&self) -> bool {
3901        self.has_conflict
3902    }
3903
3904    pub fn has_diagnostics(&self) -> bool {
3905        self.excerpts
3906            .iter()
3907            .any(|excerpt| excerpt.buffer.has_diagnostics())
3908    }
3909
3910    pub fn diagnostic_group<'a, O>(
3911        &'a self,
3912        group_id: usize,
3913    ) -> impl Iterator<Item = DiagnosticEntry<O>> + 'a
3914    where
3915        O: text::FromAnchor + 'a,
3916    {
3917        self.as_singleton()
3918            .into_iter()
3919            .flat_map(move |(_, _, buffer)| buffer.diagnostic_group(group_id))
3920    }
3921
3922    pub fn diagnostics_in_range<'a, T, O>(
3923        &'a self,
3924        range: Range<T>,
3925        reversed: bool,
3926    ) -> impl Iterator<Item = DiagnosticEntry<O>> + 'a
3927    where
3928        T: 'a + ToOffset,
3929        O: 'a + text::FromAnchor + Ord,
3930    {
3931        self.as_singleton()
3932            .into_iter()
3933            .flat_map(move |(_, _, buffer)| {
3934                buffer.diagnostics_in_range(
3935                    range.start.to_offset(self)..range.end.to_offset(self),
3936                    reversed,
3937                )
3938            })
3939    }
3940
3941    pub fn syntax_ancestor<T: ToOffset>(
3942        &self,
3943        range: Range<T>,
3944    ) -> Option<(tree_sitter::Node, Range<usize>)> {
3945        let range = range.start.to_offset(self)..range.end.to_offset(self);
3946        let excerpt = self.excerpt_containing(range.clone())?;
3947        let node = excerpt
3948            .buffer()
3949            .syntax_ancestor(excerpt.map_range_to_buffer(range))?;
3950        Some((node, excerpt.map_range_from_buffer(node.byte_range())))
3951    }
3952
3953    pub fn outline(&self, theme: Option<&SyntaxTheme>) -> Option<Outline<Anchor>> {
3954        let (excerpt_id, _, buffer) = self.as_singleton()?;
3955        let outline = buffer.outline(theme)?;
3956        Some(Outline::new(
3957            outline
3958                .items
3959                .into_iter()
3960                .flat_map(|item| {
3961                    Some(OutlineItem {
3962                        depth: item.depth,
3963                        range: self.anchor_in_excerpt(*excerpt_id, item.range.start)?
3964                            ..self.anchor_in_excerpt(*excerpt_id, item.range.end)?,
3965                        text: item.text,
3966                        highlight_ranges: item.highlight_ranges,
3967                        name_ranges: item.name_ranges,
3968                        body_range: item.body_range.and_then(|body_range| {
3969                            Some(
3970                                self.anchor_in_excerpt(*excerpt_id, body_range.start)?
3971                                    ..self.anchor_in_excerpt(*excerpt_id, body_range.end)?,
3972                            )
3973                        }),
3974                        annotation_range: item.annotation_range.and_then(|annotation_range| {
3975                            Some(
3976                                self.anchor_in_excerpt(*excerpt_id, annotation_range.start)?
3977                                    ..self.anchor_in_excerpt(*excerpt_id, annotation_range.end)?,
3978                            )
3979                        }),
3980                    })
3981                })
3982                .collect(),
3983        ))
3984    }
3985
3986    pub fn symbols_containing<T: ToOffset>(
3987        &self,
3988        offset: T,
3989        theme: Option<&SyntaxTheme>,
3990    ) -> Option<(BufferId, Vec<OutlineItem<Anchor>>)> {
3991        let anchor = self.anchor_before(offset);
3992        let excerpt_id = anchor.excerpt_id;
3993        let excerpt = self.excerpt(excerpt_id)?;
3994        Some((
3995            excerpt.buffer_id,
3996            excerpt
3997                .buffer
3998                .symbols_containing(anchor.text_anchor, theme)
3999                .into_iter()
4000                .flatten()
4001                .flat_map(|item| {
4002                    Some(OutlineItem {
4003                        depth: item.depth,
4004                        range: self.anchor_in_excerpt(excerpt_id, item.range.start)?
4005                            ..self.anchor_in_excerpt(excerpt_id, item.range.end)?,
4006                        text: item.text,
4007                        highlight_ranges: item.highlight_ranges,
4008                        name_ranges: item.name_ranges,
4009                        body_range: item.body_range.and_then(|body_range| {
4010                            Some(
4011                                self.anchor_in_excerpt(excerpt_id, body_range.start)?
4012                                    ..self.anchor_in_excerpt(excerpt_id, body_range.end)?,
4013                            )
4014                        }),
4015                        annotation_range: item.annotation_range.and_then(|body_range| {
4016                            Some(
4017                                self.anchor_in_excerpt(excerpt_id, body_range.start)?
4018                                    ..self.anchor_in_excerpt(excerpt_id, body_range.end)?,
4019                            )
4020                        }),
4021                    })
4022                })
4023                .collect(),
4024        ))
4025    }
4026
4027    fn excerpt_locator_for_id(&self, id: ExcerptId) -> &Locator {
4028        if id == ExcerptId::min() {
4029            Locator::min_ref()
4030        } else if id == ExcerptId::max() {
4031            Locator::max_ref()
4032        } else {
4033            let mut cursor = self.excerpt_ids.cursor::<ExcerptId>(&());
4034            cursor.seek(&id, Bias::Left, &());
4035            if let Some(entry) = cursor.item() {
4036                if entry.id == id {
4037                    return &entry.locator;
4038                }
4039            }
4040            panic!("invalid excerpt id {:?}", id)
4041        }
4042    }
4043
4044    /// Returns the locators referenced by the given excerpt IDs, sorted by locator.
4045    fn excerpt_locators_for_ids(
4046        &self,
4047        ids: impl IntoIterator<Item = ExcerptId>,
4048    ) -> SmallVec<[Locator; 1]> {
4049        let mut sorted_ids = ids.into_iter().collect::<SmallVec<[_; 1]>>();
4050        sorted_ids.sort_unstable();
4051        let mut locators = SmallVec::new();
4052
4053        while sorted_ids.last() == Some(&ExcerptId::max()) {
4054            sorted_ids.pop();
4055            if let Some(mapping) = self.excerpt_ids.last() {
4056                locators.push(mapping.locator.clone());
4057            }
4058        }
4059
4060        let mut sorted_ids = sorted_ids.into_iter().dedup().peekable();
4061        if sorted_ids.peek() == Some(&ExcerptId::min()) {
4062            sorted_ids.next();
4063            if let Some(mapping) = self.excerpt_ids.first() {
4064                locators.push(mapping.locator.clone());
4065            }
4066        }
4067
4068        let mut cursor = self.excerpt_ids.cursor::<ExcerptId>(&());
4069        for id in sorted_ids {
4070            if cursor.seek_forward(&id, Bias::Left, &()) {
4071                locators.push(cursor.item().unwrap().locator.clone());
4072            } else {
4073                panic!("invalid excerpt id {:?}", id);
4074            }
4075        }
4076
4077        locators.sort_unstable();
4078        locators
4079    }
4080
4081    pub fn buffer_id_for_excerpt(&self, excerpt_id: ExcerptId) -> Option<BufferId> {
4082        Some(self.excerpt(excerpt_id)?.buffer_id)
4083    }
4084
4085    pub fn buffer_for_excerpt(&self, excerpt_id: ExcerptId) -> Option<&BufferSnapshot> {
4086        Some(&self.excerpt(excerpt_id)?.buffer)
4087    }
4088
4089    pub fn range_for_excerpt<'a, T: sum_tree::Dimension<'a, ExcerptSummary>>(
4090        &'a self,
4091        excerpt_id: ExcerptId,
4092    ) -> Option<Range<T>> {
4093        let mut cursor = self.excerpts.cursor::<(Option<&Locator>, T)>(&());
4094        let locator = self.excerpt_locator_for_id(excerpt_id);
4095        if cursor.seek(&Some(locator), Bias::Left, &()) {
4096            let start = cursor.start().1.clone();
4097            let end = cursor.end(&()).1;
4098            Some(start..end)
4099        } else {
4100            None
4101        }
4102    }
4103
4104    fn excerpt(&self, excerpt_id: ExcerptId) -> Option<&Excerpt> {
4105        let mut cursor = self.excerpts.cursor::<Option<&Locator>>(&());
4106        let locator = self.excerpt_locator_for_id(excerpt_id);
4107        cursor.seek(&Some(locator), Bias::Left, &());
4108        if let Some(excerpt) = cursor.item() {
4109            if excerpt.id == excerpt_id {
4110                return Some(excerpt);
4111            }
4112        }
4113        None
4114    }
4115
4116    /// Returns the excerpt containing range and its offset start within the multibuffer or none if `range` spans multiple excerpts
4117    pub fn excerpt_containing<T: ToOffset>(&self, range: Range<T>) -> Option<MultiBufferExcerpt> {
4118        let range = range.start.to_offset(self)..range.end.to_offset(self);
4119
4120        let mut cursor = self.excerpts.cursor::<(usize, Point)>(&());
4121        cursor.seek(&range.start, Bias::Right, &());
4122        let start_excerpt = cursor.item()?;
4123
4124        if range.start == range.end {
4125            return Some(MultiBufferExcerpt::new(start_excerpt, *cursor.start()));
4126        }
4127
4128        cursor.seek(&range.end, Bias::Right, &());
4129        let end_excerpt = cursor.item()?;
4130
4131        if start_excerpt.id == end_excerpt.id {
4132            Some(MultiBufferExcerpt::new(start_excerpt, *cursor.start()))
4133        } else {
4134            None
4135        }
4136    }
4137
4138    // Takes an iterator over anchor ranges and returns a new iterator over anchor ranges that don't
4139    // span across excerpt boundaries.
4140    pub fn split_ranges<'a, I>(&'a self, ranges: I) -> impl Iterator<Item = Range<Anchor>> + 'a
4141    where
4142        I: IntoIterator<Item = Range<Anchor>> + 'a,
4143    {
4144        let mut ranges = ranges.into_iter().map(|range| range.to_offset(self));
4145        let mut cursor = self.excerpts.cursor::<(usize, Point)>(&());
4146        cursor.next(&());
4147        let mut current_range = ranges.next();
4148        iter::from_fn(move || {
4149            let range = current_range.clone()?;
4150            if range.start >= cursor.end(&()).0 {
4151                cursor.seek_forward(&range.start, Bias::Right, &());
4152                if range.start == self.len() {
4153                    cursor.prev(&());
4154                }
4155            }
4156
4157            let excerpt = cursor.item()?;
4158            let range_start_in_excerpt = cmp::max(range.start, cursor.start().0);
4159            let range_end_in_excerpt = if excerpt.has_trailing_newline {
4160                cmp::min(range.end, cursor.end(&()).0 - 1)
4161            } else {
4162                cmp::min(range.end, cursor.end(&()).0)
4163            };
4164            let buffer_range = MultiBufferExcerpt::new(excerpt, *cursor.start())
4165                .map_range_to_buffer(range_start_in_excerpt..range_end_in_excerpt);
4166
4167            let subrange_start_anchor = Anchor {
4168                buffer_id: Some(excerpt.buffer_id),
4169                excerpt_id: excerpt.id,
4170                text_anchor: excerpt.buffer.anchor_before(buffer_range.start),
4171            };
4172            let subrange_end_anchor = Anchor {
4173                buffer_id: Some(excerpt.buffer_id),
4174                excerpt_id: excerpt.id,
4175                text_anchor: excerpt.buffer.anchor_after(buffer_range.end),
4176            };
4177
4178            if range.end > cursor.end(&()).0 {
4179                cursor.next(&());
4180            } else {
4181                current_range = ranges.next();
4182            }
4183
4184            Some(subrange_start_anchor..subrange_end_anchor)
4185        })
4186    }
4187
4188    /// Returns excerpts overlapping the given ranges. If range spans multiple excerpts returns one range for each excerpt
4189    ///
4190    /// The ranges are specified in the coordinate space of the multibuffer, not the individual excerpted buffers.
4191    /// Each returned excerpt's range is in the coordinate space of its source buffer.
4192    pub fn excerpts_in_ranges(
4193        &self,
4194        ranges: impl IntoIterator<Item = Range<Anchor>>,
4195    ) -> impl Iterator<Item = (ExcerptId, &BufferSnapshot, Range<usize>)> {
4196        let mut ranges = ranges.into_iter().map(|range| range.to_offset(self));
4197        let mut cursor = self.excerpts.cursor::<(usize, Point)>(&());
4198        cursor.next(&());
4199        let mut current_range = ranges.next();
4200        iter::from_fn(move || {
4201            let range = current_range.clone()?;
4202            if range.start >= cursor.end(&()).0 {
4203                cursor.seek_forward(&range.start, Bias::Right, &());
4204                if range.start == self.len() {
4205                    cursor.prev(&());
4206                }
4207            }
4208
4209            let excerpt = cursor.item()?;
4210            let range_start_in_excerpt = cmp::max(range.start, cursor.start().0);
4211            let range_end_in_excerpt = if excerpt.has_trailing_newline {
4212                cmp::min(range.end, cursor.end(&()).0 - 1)
4213            } else {
4214                cmp::min(range.end, cursor.end(&()).0)
4215            };
4216            let buffer_range = MultiBufferExcerpt::new(excerpt, *cursor.start())
4217                .map_range_to_buffer(range_start_in_excerpt..range_end_in_excerpt);
4218
4219            if range.end > cursor.end(&()).0 {
4220                cursor.next(&());
4221            } else {
4222                current_range = ranges.next();
4223            }
4224
4225            Some((excerpt.id, &excerpt.buffer, buffer_range))
4226        })
4227    }
4228
4229    pub fn selections_in_range<'a>(
4230        &'a self,
4231        range: &'a Range<Anchor>,
4232        include_local: bool,
4233    ) -> impl 'a + Iterator<Item = (ReplicaId, bool, CursorShape, Selection<Anchor>)> {
4234        let mut cursor = self.excerpts.cursor::<ExcerptSummary>(&());
4235        let start_locator = self.excerpt_locator_for_id(range.start.excerpt_id);
4236        let end_locator = self.excerpt_locator_for_id(range.end.excerpt_id);
4237        cursor.seek(start_locator, Bias::Left, &());
4238        cursor
4239            .take_while(move |excerpt| excerpt.locator <= *end_locator)
4240            .flat_map(move |excerpt| {
4241                let mut query_range = excerpt.range.context.start..excerpt.range.context.end;
4242                if excerpt.id == range.start.excerpt_id {
4243                    query_range.start = range.start.text_anchor;
4244                }
4245                if excerpt.id == range.end.excerpt_id {
4246                    query_range.end = range.end.text_anchor;
4247                }
4248
4249                excerpt
4250                    .buffer
4251                    .selections_in_range(query_range, include_local)
4252                    .flat_map(move |(replica_id, line_mode, cursor_shape, selections)| {
4253                        selections.map(move |selection| {
4254                            let mut start = Anchor {
4255                                buffer_id: Some(excerpt.buffer_id),
4256                                excerpt_id: excerpt.id,
4257                                text_anchor: selection.start,
4258                            };
4259                            let mut end = Anchor {
4260                                buffer_id: Some(excerpt.buffer_id),
4261                                excerpt_id: excerpt.id,
4262                                text_anchor: selection.end,
4263                            };
4264                            if range.start.cmp(&start, self).is_gt() {
4265                                start = range.start;
4266                            }
4267                            if range.end.cmp(&end, self).is_lt() {
4268                                end = range.end;
4269                            }
4270
4271                            (
4272                                replica_id,
4273                                line_mode,
4274                                cursor_shape,
4275                                Selection {
4276                                    id: selection.id,
4277                                    start,
4278                                    end,
4279                                    reversed: selection.reversed,
4280                                    goal: selection.goal,
4281                                },
4282                            )
4283                        })
4284                    })
4285            })
4286    }
4287
4288    pub fn show_headers(&self) -> bool {
4289        self.show_headers
4290    }
4291}
4292
4293#[cfg(any(test, feature = "test-support"))]
4294impl MultiBufferSnapshot {
4295    pub fn random_byte_range(&self, start_offset: usize, rng: &mut impl rand::Rng) -> Range<usize> {
4296        let end = self.clip_offset(rng.gen_range(start_offset..=self.len()), Bias::Right);
4297        let start = self.clip_offset(rng.gen_range(start_offset..=end), Bias::Right);
4298        start..end
4299    }
4300}
4301
4302impl History {
4303    fn start_transaction(&mut self, now: Instant) -> Option<TransactionId> {
4304        self.transaction_depth += 1;
4305        if self.transaction_depth == 1 {
4306            let id = self.next_transaction_id.tick();
4307            self.undo_stack.push(Transaction {
4308                id,
4309                buffer_transactions: Default::default(),
4310                first_edit_at: now,
4311                last_edit_at: now,
4312                suppress_grouping: false,
4313            });
4314            Some(id)
4315        } else {
4316            None
4317        }
4318    }
4319
4320    fn end_transaction(
4321        &mut self,
4322        now: Instant,
4323        buffer_transactions: HashMap<BufferId, TransactionId>,
4324    ) -> bool {
4325        assert_ne!(self.transaction_depth, 0);
4326        self.transaction_depth -= 1;
4327        if self.transaction_depth == 0 {
4328            if buffer_transactions.is_empty() {
4329                self.undo_stack.pop();
4330                false
4331            } else {
4332                self.redo_stack.clear();
4333                let transaction = self.undo_stack.last_mut().unwrap();
4334                transaction.last_edit_at = now;
4335                for (buffer_id, transaction_id) in buffer_transactions {
4336                    transaction
4337                        .buffer_transactions
4338                        .entry(buffer_id)
4339                        .or_insert(transaction_id);
4340                }
4341                true
4342            }
4343        } else {
4344            false
4345        }
4346    }
4347
4348    fn push_transaction<'a, T>(
4349        &mut self,
4350        buffer_transactions: T,
4351        now: Instant,
4352        cx: &ModelContext<MultiBuffer>,
4353    ) where
4354        T: IntoIterator<Item = (&'a Model<Buffer>, &'a language::Transaction)>,
4355    {
4356        assert_eq!(self.transaction_depth, 0);
4357        let transaction = Transaction {
4358            id: self.next_transaction_id.tick(),
4359            buffer_transactions: buffer_transactions
4360                .into_iter()
4361                .map(|(buffer, transaction)| (buffer.read(cx).remote_id(), transaction.id))
4362                .collect(),
4363            first_edit_at: now,
4364            last_edit_at: now,
4365            suppress_grouping: false,
4366        };
4367        if !transaction.buffer_transactions.is_empty() {
4368            self.undo_stack.push(transaction);
4369            self.redo_stack.clear();
4370        }
4371    }
4372
4373    fn finalize_last_transaction(&mut self) {
4374        if let Some(transaction) = self.undo_stack.last_mut() {
4375            transaction.suppress_grouping = true;
4376        }
4377    }
4378
4379    fn forget(&mut self, transaction_id: TransactionId) -> Option<Transaction> {
4380        if let Some(ix) = self
4381            .undo_stack
4382            .iter()
4383            .rposition(|transaction| transaction.id == transaction_id)
4384        {
4385            Some(self.undo_stack.remove(ix))
4386        } else if let Some(ix) = self
4387            .redo_stack
4388            .iter()
4389            .rposition(|transaction| transaction.id == transaction_id)
4390        {
4391            Some(self.redo_stack.remove(ix))
4392        } else {
4393            None
4394        }
4395    }
4396
4397    fn transaction(&self, transaction_id: TransactionId) -> Option<&Transaction> {
4398        self.undo_stack
4399            .iter()
4400            .find(|transaction| transaction.id == transaction_id)
4401            .or_else(|| {
4402                self.redo_stack
4403                    .iter()
4404                    .find(|transaction| transaction.id == transaction_id)
4405            })
4406    }
4407
4408    fn transaction_mut(&mut self, transaction_id: TransactionId) -> Option<&mut Transaction> {
4409        self.undo_stack
4410            .iter_mut()
4411            .find(|transaction| transaction.id == transaction_id)
4412            .or_else(|| {
4413                self.redo_stack
4414                    .iter_mut()
4415                    .find(|transaction| transaction.id == transaction_id)
4416            })
4417    }
4418
4419    fn pop_undo(&mut self) -> Option<&mut Transaction> {
4420        assert_eq!(self.transaction_depth, 0);
4421        if let Some(transaction) = self.undo_stack.pop() {
4422            self.redo_stack.push(transaction);
4423            self.redo_stack.last_mut()
4424        } else {
4425            None
4426        }
4427    }
4428
4429    fn pop_redo(&mut self) -> Option<&mut Transaction> {
4430        assert_eq!(self.transaction_depth, 0);
4431        if let Some(transaction) = self.redo_stack.pop() {
4432            self.undo_stack.push(transaction);
4433            self.undo_stack.last_mut()
4434        } else {
4435            None
4436        }
4437    }
4438
4439    fn remove_from_undo(&mut self, transaction_id: TransactionId) -> Option<&Transaction> {
4440        let ix = self
4441            .undo_stack
4442            .iter()
4443            .rposition(|transaction| transaction.id == transaction_id)?;
4444        let transaction = self.undo_stack.remove(ix);
4445        self.redo_stack.push(transaction);
4446        self.redo_stack.last()
4447    }
4448
4449    fn group(&mut self) -> Option<TransactionId> {
4450        let mut count = 0;
4451        let mut transactions = self.undo_stack.iter();
4452        if let Some(mut transaction) = transactions.next_back() {
4453            while let Some(prev_transaction) = transactions.next_back() {
4454                if !prev_transaction.suppress_grouping
4455                    && transaction.first_edit_at - prev_transaction.last_edit_at
4456                        <= self.group_interval
4457                {
4458                    transaction = prev_transaction;
4459                    count += 1;
4460                } else {
4461                    break;
4462                }
4463            }
4464        }
4465        self.group_trailing(count)
4466    }
4467
4468    fn group_until(&mut self, transaction_id: TransactionId) {
4469        let mut count = 0;
4470        for transaction in self.undo_stack.iter().rev() {
4471            if transaction.id == transaction_id {
4472                self.group_trailing(count);
4473                break;
4474            } else if transaction.suppress_grouping {
4475                break;
4476            } else {
4477                count += 1;
4478            }
4479        }
4480    }
4481
4482    fn group_trailing(&mut self, n: usize) -> Option<TransactionId> {
4483        let new_len = self.undo_stack.len() - n;
4484        let (transactions_to_keep, transactions_to_merge) = self.undo_stack.split_at_mut(new_len);
4485        if let Some(last_transaction) = transactions_to_keep.last_mut() {
4486            if let Some(transaction) = transactions_to_merge.last() {
4487                last_transaction.last_edit_at = transaction.last_edit_at;
4488            }
4489            for to_merge in transactions_to_merge {
4490                for (buffer_id, transaction_id) in &to_merge.buffer_transactions {
4491                    last_transaction
4492                        .buffer_transactions
4493                        .entry(*buffer_id)
4494                        .or_insert(*transaction_id);
4495                }
4496            }
4497        }
4498
4499        self.undo_stack.truncate(new_len);
4500        self.undo_stack.last().map(|t| t.id)
4501    }
4502}
4503
4504impl Excerpt {
4505    fn new(
4506        id: ExcerptId,
4507        locator: Locator,
4508        buffer_id: BufferId,
4509        buffer: BufferSnapshot,
4510        range: ExcerptRange<text::Anchor>,
4511        has_trailing_newline: bool,
4512    ) -> Self {
4513        Excerpt {
4514            id,
4515            locator,
4516            max_buffer_row: range.context.end.to_point(&buffer).row,
4517            text_summary: buffer
4518                .text_summary_for_range::<TextSummary, _>(range.context.to_offset(&buffer)),
4519            buffer_id,
4520            buffer,
4521            range,
4522            has_trailing_newline,
4523        }
4524    }
4525
4526    fn chunks_in_range(&self, range: Range<usize>, language_aware: bool) -> ExcerptChunks {
4527        let content_start = self.range.context.start.to_offset(&self.buffer);
4528        let chunks_start = content_start + range.start;
4529        let chunks_end = content_start + cmp::min(range.end, self.text_summary.len);
4530
4531        let footer_height = if self.has_trailing_newline
4532            && range.start <= self.text_summary.len
4533            && range.end > self.text_summary.len
4534        {
4535            1
4536        } else {
4537            0
4538        };
4539
4540        let content_chunks = self.buffer.chunks(chunks_start..chunks_end, language_aware);
4541
4542        ExcerptChunks {
4543            excerpt_id: self.id,
4544            content_chunks,
4545            footer_height,
4546        }
4547    }
4548
4549    fn seek_chunks(&self, excerpt_chunks: &mut ExcerptChunks, range: Range<usize>) {
4550        let content_start = self.range.context.start.to_offset(&self.buffer);
4551        let chunks_start = content_start + range.start;
4552        let chunks_end = content_start + cmp::min(range.end, self.text_summary.len);
4553        excerpt_chunks.content_chunks.seek(chunks_start..chunks_end);
4554        excerpt_chunks.footer_height = if self.has_trailing_newline
4555            && range.start <= self.text_summary.len
4556            && range.end > self.text_summary.len
4557        {
4558            1
4559        } else {
4560            0
4561        };
4562    }
4563
4564    fn bytes_in_range(&self, range: Range<usize>) -> ExcerptBytes {
4565        let content_start = self.range.context.start.to_offset(&self.buffer);
4566        let bytes_start = content_start + range.start;
4567        let bytes_end = content_start + cmp::min(range.end, self.text_summary.len);
4568        let footer_height = if self.has_trailing_newline
4569            && range.start <= self.text_summary.len
4570            && range.end > self.text_summary.len
4571        {
4572            1
4573        } else {
4574            0
4575        };
4576        let content_bytes = self.buffer.bytes_in_range(bytes_start..bytes_end);
4577
4578        ExcerptBytes {
4579            content_bytes,
4580            padding_height: footer_height,
4581            reversed: false,
4582        }
4583    }
4584
4585    fn reversed_bytes_in_range(&self, range: Range<usize>) -> ExcerptBytes {
4586        let content_start = self.range.context.start.to_offset(&self.buffer);
4587        let bytes_start = content_start + range.start;
4588        let bytes_end = content_start + cmp::min(range.end, self.text_summary.len);
4589        let footer_height = if self.has_trailing_newline
4590            && range.start <= self.text_summary.len
4591            && range.end > self.text_summary.len
4592        {
4593            1
4594        } else {
4595            0
4596        };
4597        let content_bytes = self.buffer.reversed_bytes_in_range(bytes_start..bytes_end);
4598
4599        ExcerptBytes {
4600            content_bytes,
4601            padding_height: footer_height,
4602            reversed: true,
4603        }
4604    }
4605
4606    fn clip_anchor(&self, text_anchor: text::Anchor) -> text::Anchor {
4607        if text_anchor
4608            .cmp(&self.range.context.start, &self.buffer)
4609            .is_lt()
4610        {
4611            self.range.context.start
4612        } else if text_anchor
4613            .cmp(&self.range.context.end, &self.buffer)
4614            .is_gt()
4615        {
4616            self.range.context.end
4617        } else {
4618            text_anchor
4619        }
4620    }
4621
4622    fn contains(&self, anchor: &Anchor) -> bool {
4623        Some(self.buffer_id) == anchor.buffer_id
4624            && self
4625                .range
4626                .context
4627                .start
4628                .cmp(&anchor.text_anchor, &self.buffer)
4629                .is_le()
4630            && self
4631                .range
4632                .context
4633                .end
4634                .cmp(&anchor.text_anchor, &self.buffer)
4635                .is_ge()
4636    }
4637
4638    /// The [`Excerpt`]'s start offset in its [`Buffer`]
4639    fn buffer_start_offset(&self) -> usize {
4640        self.range.context.start.to_offset(&self.buffer)
4641    }
4642
4643    /// The [`Excerpt`]'s start point in its [`Buffer`]
4644    fn buffer_start_point(&self) -> Point {
4645        self.range.context.start.to_point(&self.buffer)
4646    }
4647
4648    /// The [`Excerpt`]'s end offset in its [`Buffer`]
4649    fn buffer_end_offset(&self) -> usize {
4650        self.buffer_start_offset() + self.text_summary.len
4651    }
4652}
4653
4654impl<'a> MultiBufferExcerpt<'a> {
4655    fn new(excerpt: &'a Excerpt, (excerpt_offset, excerpt_position): (usize, Point)) -> Self {
4656        MultiBufferExcerpt {
4657            excerpt,
4658            excerpt_offset,
4659            excerpt_position,
4660        }
4661    }
4662
4663    pub fn id(&self) -> ExcerptId {
4664        self.excerpt.id
4665    }
4666
4667    pub fn start_anchor(&self) -> Anchor {
4668        Anchor {
4669            buffer_id: Some(self.excerpt.buffer_id),
4670            excerpt_id: self.excerpt.id,
4671            text_anchor: self.excerpt.range.context.start,
4672        }
4673    }
4674
4675    pub fn end_anchor(&self) -> Anchor {
4676        Anchor {
4677            buffer_id: Some(self.excerpt.buffer_id),
4678            excerpt_id: self.excerpt.id,
4679            text_anchor: self.excerpt.range.context.end,
4680        }
4681    }
4682
4683    pub fn buffer(&self) -> &'a BufferSnapshot {
4684        &self.excerpt.buffer
4685    }
4686
4687    pub fn buffer_range(&self) -> Range<text::Anchor> {
4688        self.excerpt.range.context.clone()
4689    }
4690
4691    pub fn start_offset(&self) -> usize {
4692        self.excerpt_offset
4693    }
4694
4695    pub fn start_point(&self) -> Point {
4696        self.excerpt_position
4697    }
4698
4699    /// Maps an offset within the [`MultiBuffer`] to an offset within the [`Buffer`]
4700    pub fn map_offset_to_buffer(&self, offset: usize) -> usize {
4701        self.excerpt.buffer_start_offset()
4702            + offset
4703                .saturating_sub(self.excerpt_offset)
4704                .min(self.excerpt.text_summary.len)
4705    }
4706
4707    /// Maps a point within the [`MultiBuffer`] to a point within the [`Buffer`]
4708    pub fn map_point_to_buffer(&self, point: Point) -> Point {
4709        self.excerpt.buffer_start_point()
4710            + point
4711                .saturating_sub(self.excerpt_position)
4712                .min(self.excerpt.text_summary.lines)
4713    }
4714
4715    /// Maps a range within the [`MultiBuffer`] to a range within the [`Buffer`]
4716    pub fn map_range_to_buffer(&self, range: Range<usize>) -> Range<usize> {
4717        self.map_offset_to_buffer(range.start)..self.map_offset_to_buffer(range.end)
4718    }
4719
4720    /// Map an offset within the [`Buffer`] to an offset within the [`MultiBuffer`]
4721    pub fn map_offset_from_buffer(&self, buffer_offset: usize) -> usize {
4722        let buffer_offset_in_excerpt = buffer_offset
4723            .saturating_sub(self.excerpt.buffer_start_offset())
4724            .min(self.excerpt.text_summary.len);
4725        self.excerpt_offset + buffer_offset_in_excerpt
4726    }
4727
4728    /// Map a point within the [`Buffer`] to a point within the [`MultiBuffer`]
4729    pub fn map_point_from_buffer(&self, buffer_position: Point) -> Point {
4730        let position_in_excerpt = buffer_position.saturating_sub(self.excerpt.buffer_start_point());
4731        let position_in_excerpt =
4732            position_in_excerpt.min(self.excerpt.text_summary.lines + Point::new(1, 0));
4733        self.excerpt_position + position_in_excerpt
4734    }
4735
4736    /// Map a range within the [`Buffer`] to a range within the [`MultiBuffer`]
4737    pub fn map_range_from_buffer(&self, buffer_range: Range<usize>) -> Range<usize> {
4738        self.map_offset_from_buffer(buffer_range.start)
4739            ..self.map_offset_from_buffer(buffer_range.end)
4740    }
4741
4742    /// Returns true if the entirety of the given range is in the buffer's excerpt
4743    pub fn contains_buffer_range(&self, range: Range<usize>) -> bool {
4744        range.start >= self.excerpt.buffer_start_offset()
4745            && range.end <= self.excerpt.buffer_end_offset()
4746    }
4747
4748    pub fn max_buffer_row(&self) -> u32 {
4749        self.excerpt.max_buffer_row
4750    }
4751}
4752
4753impl ExcerptId {
4754    pub fn min() -> Self {
4755        Self(0)
4756    }
4757
4758    pub fn max() -> Self {
4759        Self(usize::MAX)
4760    }
4761
4762    pub fn to_proto(&self) -> u64 {
4763        self.0 as _
4764    }
4765
4766    pub fn from_proto(proto: u64) -> Self {
4767        Self(proto as _)
4768    }
4769
4770    pub fn cmp(&self, other: &Self, snapshot: &MultiBufferSnapshot) -> cmp::Ordering {
4771        let a = snapshot.excerpt_locator_for_id(*self);
4772        let b = snapshot.excerpt_locator_for_id(*other);
4773        a.cmp(b).then_with(|| self.0.cmp(&other.0))
4774    }
4775}
4776
4777impl From<ExcerptId> for usize {
4778    fn from(val: ExcerptId) -> Self {
4779        val.0
4780    }
4781}
4782
4783impl fmt::Debug for Excerpt {
4784    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
4785        f.debug_struct("Excerpt")
4786            .field("id", &self.id)
4787            .field("locator", &self.locator)
4788            .field("buffer_id", &self.buffer_id)
4789            .field("range", &self.range)
4790            .field("text_summary", &self.text_summary)
4791            .field("has_trailing_newline", &self.has_trailing_newline)
4792            .finish()
4793    }
4794}
4795
4796impl sum_tree::Item for Excerpt {
4797    type Summary = ExcerptSummary;
4798
4799    fn summary(&self, _cx: &()) -> Self::Summary {
4800        let mut text = self.text_summary.clone();
4801        if self.has_trailing_newline {
4802            text += TextSummary::from("\n");
4803        }
4804        ExcerptSummary {
4805            excerpt_id: self.id,
4806            excerpt_locator: self.locator.clone(),
4807            widest_line_number: self.max_buffer_row,
4808            text,
4809        }
4810    }
4811}
4812
4813impl sum_tree::Item for ExcerptIdMapping {
4814    type Summary = ExcerptId;
4815
4816    fn summary(&self, _cx: &()) -> Self::Summary {
4817        self.id
4818    }
4819}
4820
4821impl sum_tree::KeyedItem for ExcerptIdMapping {
4822    type Key = ExcerptId;
4823
4824    fn key(&self) -> Self::Key {
4825        self.id
4826    }
4827}
4828
4829impl sum_tree::Summary for ExcerptId {
4830    type Context = ();
4831
4832    fn zero(_cx: &()) -> Self {
4833        Default::default()
4834    }
4835
4836    fn add_summary(&mut self, other: &Self, _: &()) {
4837        *self = *other;
4838    }
4839}
4840
4841impl sum_tree::Summary for ExcerptSummary {
4842    type Context = ();
4843
4844    fn zero(_cx: &()) -> Self {
4845        Default::default()
4846    }
4847
4848    fn add_summary(&mut self, summary: &Self, _: &()) {
4849        debug_assert!(summary.excerpt_locator > self.excerpt_locator);
4850        self.excerpt_locator = summary.excerpt_locator.clone();
4851        self.text.add_summary(&summary.text, &());
4852        self.widest_line_number = cmp::max(self.widest_line_number, summary.widest_line_number);
4853    }
4854}
4855
4856impl<'a> sum_tree::Dimension<'a, ExcerptSummary> for TextSummary {
4857    fn zero(_cx: &()) -> Self {
4858        Default::default()
4859    }
4860
4861    fn add_summary(&mut self, summary: &'a ExcerptSummary, _: &()) {
4862        *self += &summary.text;
4863    }
4864}
4865
4866impl<'a> sum_tree::Dimension<'a, ExcerptSummary> for usize {
4867    fn zero(_cx: &()) -> Self {
4868        Default::default()
4869    }
4870
4871    fn add_summary(&mut self, summary: &'a ExcerptSummary, _: &()) {
4872        *self += summary.text.len;
4873    }
4874}
4875
4876impl<'a> sum_tree::SeekTarget<'a, ExcerptSummary, ExcerptSummary> for usize {
4877    fn cmp(&self, cursor_location: &ExcerptSummary, _: &()) -> cmp::Ordering {
4878        Ord::cmp(self, &cursor_location.text.len)
4879    }
4880}
4881
4882impl<'a> sum_tree::SeekTarget<'a, ExcerptSummary, TextSummary> for Point {
4883    fn cmp(&self, cursor_location: &TextSummary, _: &()) -> cmp::Ordering {
4884        Ord::cmp(self, &cursor_location.lines)
4885    }
4886}
4887
4888impl<'a> sum_tree::SeekTarget<'a, ExcerptSummary, Option<&'a Locator>> for Locator {
4889    fn cmp(&self, cursor_location: &Option<&'a Locator>, _: &()) -> cmp::Ordering {
4890        Ord::cmp(&Some(self), cursor_location)
4891    }
4892}
4893
4894impl<'a> sum_tree::SeekTarget<'a, ExcerptSummary, ExcerptSummary> for Locator {
4895    fn cmp(&self, cursor_location: &ExcerptSummary, _: &()) -> cmp::Ordering {
4896        Ord::cmp(self, &cursor_location.excerpt_locator)
4897    }
4898}
4899
4900impl<'a> sum_tree::Dimension<'a, ExcerptSummary> for OffsetUtf16 {
4901    fn zero(_cx: &()) -> Self {
4902        Default::default()
4903    }
4904
4905    fn add_summary(&mut self, summary: &'a ExcerptSummary, _: &()) {
4906        *self += summary.text.len_utf16;
4907    }
4908}
4909
4910impl<'a> sum_tree::Dimension<'a, ExcerptSummary> for Point {
4911    fn zero(_cx: &()) -> Self {
4912        Default::default()
4913    }
4914
4915    fn add_summary(&mut self, summary: &'a ExcerptSummary, _: &()) {
4916        *self += summary.text.lines;
4917    }
4918}
4919
4920impl<'a> sum_tree::Dimension<'a, ExcerptSummary> for PointUtf16 {
4921    fn zero(_cx: &()) -> Self {
4922        Default::default()
4923    }
4924
4925    fn add_summary(&mut self, summary: &'a ExcerptSummary, _: &()) {
4926        *self += summary.text.lines_utf16()
4927    }
4928}
4929
4930impl<'a> sum_tree::Dimension<'a, ExcerptSummary> for Option<&'a Locator> {
4931    fn zero(_cx: &()) -> Self {
4932        Default::default()
4933    }
4934
4935    fn add_summary(&mut self, summary: &'a ExcerptSummary, _: &()) {
4936        *self = Some(&summary.excerpt_locator);
4937    }
4938}
4939
4940impl<'a> sum_tree::Dimension<'a, ExcerptSummary> for Option<ExcerptId> {
4941    fn zero(_cx: &()) -> Self {
4942        Default::default()
4943    }
4944
4945    fn add_summary(&mut self, summary: &'a ExcerptSummary, _: &()) {
4946        *self = Some(summary.excerpt_id);
4947    }
4948}
4949
4950impl<'a> MultiBufferRows<'a> {
4951    pub fn seek(&mut self, row: MultiBufferRow) {
4952        self.buffer_row_range = 0..0;
4953
4954        self.excerpts
4955            .seek_forward(&Point::new(row.0, 0), Bias::Right, &());
4956        if self.excerpts.item().is_none() {
4957            self.excerpts.prev(&());
4958
4959            if self.excerpts.item().is_none() && row.0 == 0 {
4960                self.buffer_row_range = 0..1;
4961                return;
4962            }
4963        }
4964
4965        if let Some(excerpt) = self.excerpts.item() {
4966            let overshoot = row.0 - self.excerpts.start().row;
4967            let excerpt_start = excerpt.range.context.start.to_point(&excerpt.buffer).row;
4968            self.buffer_row_range.start = excerpt_start + overshoot;
4969            self.buffer_row_range.end = excerpt_start + excerpt.text_summary.lines.row + 1;
4970        }
4971    }
4972}
4973
4974impl<'a> Iterator for MultiBufferRows<'a> {
4975    type Item = Option<u32>;
4976
4977    fn next(&mut self) -> Option<Self::Item> {
4978        loop {
4979            if !self.buffer_row_range.is_empty() {
4980                let row = Some(self.buffer_row_range.start);
4981                self.buffer_row_range.start += 1;
4982                return Some(row);
4983            }
4984            self.excerpts.item()?;
4985            self.excerpts.next(&());
4986            let excerpt = self.excerpts.item()?;
4987            self.buffer_row_range.start = excerpt.range.context.start.to_point(&excerpt.buffer).row;
4988            self.buffer_row_range.end =
4989                self.buffer_row_range.start + excerpt.text_summary.lines.row + 1;
4990        }
4991    }
4992}
4993
4994impl<'a> MultiBufferChunks<'a> {
4995    pub fn offset(&self) -> usize {
4996        self.range.start
4997    }
4998
4999    pub fn seek(&mut self, new_range: Range<usize>) {
5000        self.range = new_range.clone();
5001        self.excerpts.seek(&new_range.start, Bias::Right, &());
5002        if let Some(excerpt) = self.excerpts.item() {
5003            let excerpt_start = self.excerpts.start();
5004            if let Some(excerpt_chunks) = self
5005                .excerpt_chunks
5006                .as_mut()
5007                .filter(|chunks| excerpt.id == chunks.excerpt_id)
5008            {
5009                excerpt.seek_chunks(
5010                    excerpt_chunks,
5011                    self.range.start - excerpt_start..self.range.end - excerpt_start,
5012                );
5013            } else {
5014                self.excerpt_chunks = Some(excerpt.chunks_in_range(
5015                    self.range.start - excerpt_start..self.range.end - excerpt_start,
5016                    self.language_aware,
5017                ));
5018            }
5019        } else {
5020            self.excerpt_chunks = None;
5021        }
5022    }
5023}
5024
5025impl<'a> Iterator for MultiBufferChunks<'a> {
5026    type Item = Chunk<'a>;
5027
5028    fn next(&mut self) -> Option<Self::Item> {
5029        if self.range.is_empty() {
5030            None
5031        } else if let Some(chunk) = self.excerpt_chunks.as_mut()?.next() {
5032            self.range.start += chunk.text.len();
5033            Some(chunk)
5034        } else {
5035            self.excerpts.next(&());
5036            let excerpt = self.excerpts.item()?;
5037            self.excerpt_chunks = Some(excerpt.chunks_in_range(
5038                0..self.range.end - self.excerpts.start(),
5039                self.language_aware,
5040            ));
5041            self.next()
5042        }
5043    }
5044}
5045
5046impl<'a> MultiBufferBytes<'a> {
5047    fn consume(&mut self, len: usize) {
5048        self.range.start += len;
5049        self.chunk = &self.chunk[len..];
5050
5051        if !self.range.is_empty() && self.chunk.is_empty() {
5052            if let Some(chunk) = self.excerpt_bytes.as_mut().and_then(|bytes| bytes.next()) {
5053                self.chunk = chunk;
5054            } else {
5055                self.excerpts.next(&());
5056                if let Some(excerpt) = self.excerpts.item() {
5057                    let mut excerpt_bytes =
5058                        excerpt.bytes_in_range(0..self.range.end - self.excerpts.start());
5059                    self.chunk = excerpt_bytes.next().unwrap();
5060                    self.excerpt_bytes = Some(excerpt_bytes);
5061                }
5062            }
5063        }
5064    }
5065}
5066
5067impl<'a> Iterator for MultiBufferBytes<'a> {
5068    type Item = &'a [u8];
5069
5070    fn next(&mut self) -> Option<Self::Item> {
5071        let chunk = self.chunk;
5072        if chunk.is_empty() {
5073            None
5074        } else {
5075            self.consume(chunk.len());
5076            Some(chunk)
5077        }
5078    }
5079}
5080
5081impl<'a> io::Read for MultiBufferBytes<'a> {
5082    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
5083        let len = cmp::min(buf.len(), self.chunk.len());
5084        buf[..len].copy_from_slice(&self.chunk[..len]);
5085        if len > 0 {
5086            self.consume(len);
5087        }
5088        Ok(len)
5089    }
5090}
5091
5092impl<'a> ReversedMultiBufferBytes<'a> {
5093    fn consume(&mut self, len: usize) {
5094        self.range.end -= len;
5095        self.chunk = &self.chunk[..self.chunk.len() - len];
5096
5097        if !self.range.is_empty() && self.chunk.is_empty() {
5098            if let Some(chunk) = self.excerpt_bytes.as_mut().and_then(|bytes| bytes.next()) {
5099                self.chunk = chunk;
5100            } else {
5101                self.excerpts.prev(&());
5102                if let Some(excerpt) = self.excerpts.item() {
5103                    let mut excerpt_bytes = excerpt.reversed_bytes_in_range(
5104                        self.range.start.saturating_sub(*self.excerpts.start())..usize::MAX,
5105                    );
5106                    self.chunk = excerpt_bytes.next().unwrap();
5107                    self.excerpt_bytes = Some(excerpt_bytes);
5108                }
5109            }
5110        }
5111    }
5112}
5113
5114impl<'a> io::Read for ReversedMultiBufferBytes<'a> {
5115    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
5116        let len = cmp::min(buf.len(), self.chunk.len());
5117        buf[..len].copy_from_slice(&self.chunk[..len]);
5118        buf[..len].reverse();
5119        if len > 0 {
5120            self.consume(len);
5121        }
5122        Ok(len)
5123    }
5124}
5125impl<'a> Iterator for ExcerptBytes<'a> {
5126    type Item = &'a [u8];
5127
5128    fn next(&mut self) -> Option<Self::Item> {
5129        if self.reversed && self.padding_height > 0 {
5130            let result = &NEWLINES[..self.padding_height];
5131            self.padding_height = 0;
5132            return Some(result);
5133        }
5134
5135        if let Some(chunk) = self.content_bytes.next() {
5136            if !chunk.is_empty() {
5137                return Some(chunk);
5138            }
5139        }
5140
5141        if self.padding_height > 0 {
5142            let result = &NEWLINES[..self.padding_height];
5143            self.padding_height = 0;
5144            return Some(result);
5145        }
5146
5147        None
5148    }
5149}
5150
5151impl<'a> Iterator for ExcerptChunks<'a> {
5152    type Item = Chunk<'a>;
5153
5154    fn next(&mut self) -> Option<Self::Item> {
5155        if let Some(chunk) = self.content_chunks.next() {
5156            return Some(chunk);
5157        }
5158
5159        if self.footer_height > 0 {
5160            let text = unsafe { str::from_utf8_unchecked(&NEWLINES[..self.footer_height]) };
5161            self.footer_height = 0;
5162            return Some(Chunk {
5163                text,
5164                ..Default::default()
5165            });
5166        }
5167
5168        None
5169    }
5170}
5171
5172impl ToOffset for Point {
5173    fn to_offset<'a>(&self, snapshot: &MultiBufferSnapshot) -> usize {
5174        snapshot.point_to_offset(*self)
5175    }
5176}
5177
5178impl ToOffset for usize {
5179    fn to_offset<'a>(&self, snapshot: &MultiBufferSnapshot) -> usize {
5180        assert!(*self <= snapshot.len(), "offset is out of range");
5181        *self
5182    }
5183}
5184
5185impl ToOffset for OffsetUtf16 {
5186    fn to_offset<'a>(&self, snapshot: &MultiBufferSnapshot) -> usize {
5187        snapshot.offset_utf16_to_offset(*self)
5188    }
5189}
5190
5191impl ToOffset for PointUtf16 {
5192    fn to_offset<'a>(&self, snapshot: &MultiBufferSnapshot) -> usize {
5193        snapshot.point_utf16_to_offset(*self)
5194    }
5195}
5196
5197impl ToOffsetUtf16 for OffsetUtf16 {
5198    fn to_offset_utf16(&self, _snapshot: &MultiBufferSnapshot) -> OffsetUtf16 {
5199        *self
5200    }
5201}
5202
5203impl ToOffsetUtf16 for usize {
5204    fn to_offset_utf16(&self, snapshot: &MultiBufferSnapshot) -> OffsetUtf16 {
5205        snapshot.offset_to_offset_utf16(*self)
5206    }
5207}
5208
5209impl ToPoint for usize {
5210    fn to_point<'a>(&self, snapshot: &MultiBufferSnapshot) -> Point {
5211        snapshot.offset_to_point(*self)
5212    }
5213}
5214
5215impl ToPoint for Point {
5216    fn to_point<'a>(&self, _: &MultiBufferSnapshot) -> Point {
5217        *self
5218    }
5219}
5220
5221impl ToPointUtf16 for usize {
5222    fn to_point_utf16<'a>(&self, snapshot: &MultiBufferSnapshot) -> PointUtf16 {
5223        snapshot.offset_to_point_utf16(*self)
5224    }
5225}
5226
5227impl ToPointUtf16 for Point {
5228    fn to_point_utf16<'a>(&self, snapshot: &MultiBufferSnapshot) -> PointUtf16 {
5229        snapshot.point_to_point_utf16(*self)
5230    }
5231}
5232
5233impl ToPointUtf16 for PointUtf16 {
5234    fn to_point_utf16<'a>(&self, _: &MultiBufferSnapshot) -> PointUtf16 {
5235        *self
5236    }
5237}
5238
5239pub fn build_excerpt_ranges<T>(
5240    buffer: &BufferSnapshot,
5241    ranges: &[Range<T>],
5242    context_line_count: u32,
5243) -> (Vec<ExcerptRange<Point>>, Vec<usize>)
5244where
5245    T: text::ToPoint,
5246{
5247    let max_point = buffer.max_point();
5248    let mut range_counts = Vec::new();
5249    let mut excerpt_ranges = Vec::new();
5250    let mut range_iter = ranges
5251        .iter()
5252        .map(|range| range.start.to_point(buffer)..range.end.to_point(buffer))
5253        .peekable();
5254    while let Some(range) = range_iter.next() {
5255        let excerpt_start = Point::new(range.start.row.saturating_sub(context_line_count), 0);
5256        let row = (range.end.row + context_line_count).min(max_point.row);
5257        let mut excerpt_end = Point::new(row, buffer.line_len(row));
5258
5259        let mut ranges_in_excerpt = 1;
5260
5261        while let Some(next_range) = range_iter.peek() {
5262            if next_range.start.row <= excerpt_end.row + context_line_count {
5263                let row = (next_range.end.row + context_line_count).min(max_point.row);
5264                excerpt_end = Point::new(row, buffer.line_len(row));
5265
5266                ranges_in_excerpt += 1;
5267                range_iter.next();
5268            } else {
5269                break;
5270            }
5271        }
5272
5273        excerpt_ranges.push(ExcerptRange {
5274            context: excerpt_start..excerpt_end,
5275            primary: Some(range),
5276        });
5277        range_counts.push(ranges_in_excerpt);
5278    }
5279
5280    (excerpt_ranges, range_counts)
5281}