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