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