multi_buffer.rs

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