multi_buffer.rs

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