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