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