multi_buffer.rs

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