multi_buffer.rs

   1mod anchor;
   2
   3pub use anchor::{Anchor, AnchorRangeExt};
   4use anyhow::Result;
   5use clock::ReplicaId;
   6use collections::{Bound, HashMap, HashSet};
   7use gpui::{AppContext, Entity, ModelContext, ModelHandle, Task};
   8pub use language::Completion;
   9use language::{
  10    Buffer, BufferChunks, BufferSnapshot, Chunk, DiagnosticEntry, Event, File, Language, Outline,
  11    OutlineItem, Selection, ToOffset as _, ToPoint as _, ToPointUtf16 as _, TransactionId,
  12};
  13use std::{
  14    cell::{Ref, RefCell},
  15    cmp, fmt, io,
  16    iter::{self, FromIterator},
  17    ops::{Range, RangeBounds, Sub},
  18    str,
  19    sync::Arc,
  20    time::{Duration, Instant},
  21};
  22use sum_tree::{Bias, Cursor, SumTree};
  23use text::{
  24    locator::Locator,
  25    rope::TextDimension,
  26    subscription::{Subscription, Topic},
  27    AnchorRangeExt as _, Edit, Point, PointUtf16, TextSummary,
  28};
  29use theme::SyntaxTheme;
  30
  31const NEWLINES: &'static [u8] = &[b'\n'; u8::MAX as usize];
  32
  33pub type ExcerptId = Locator;
  34
  35pub struct MultiBuffer {
  36    snapshot: RefCell<MultiBufferSnapshot>,
  37    buffers: RefCell<HashMap<usize, BufferState>>,
  38    subscriptions: Topic,
  39    singleton: bool,
  40    replica_id: ReplicaId,
  41    history: History,
  42}
  43
  44struct History {
  45    next_transaction_id: TransactionId,
  46    undo_stack: Vec<Transaction>,
  47    redo_stack: Vec<Transaction>,
  48    transaction_depth: usize,
  49    group_interval: Duration,
  50}
  51
  52#[derive(Copy, Clone, Eq, PartialEq, PartialOrd, Ord, Debug)]
  53pub enum CharKind {
  54    Newline,
  55    Punctuation,
  56    Whitespace,
  57    Word,
  58}
  59
  60struct Transaction {
  61    id: TransactionId,
  62    buffer_transactions: HashSet<(usize, text::TransactionId)>,
  63    first_edit_at: Instant,
  64    last_edit_at: Instant,
  65}
  66
  67pub trait ToOffset: 'static + fmt::Debug {
  68    fn to_offset(&self, snapshot: &MultiBufferSnapshot) -> usize;
  69}
  70
  71pub trait ToPoint: 'static + fmt::Debug {
  72    fn to_point(&self, snapshot: &MultiBufferSnapshot) -> Point;
  73}
  74
  75pub trait ToPointUtf16: 'static + fmt::Debug {
  76    fn to_point_utf16(&self, snapshot: &MultiBufferSnapshot) -> PointUtf16;
  77}
  78
  79struct BufferState {
  80    buffer: ModelHandle<Buffer>,
  81    last_version: clock::Global,
  82    last_parse_count: usize,
  83    last_selections_update_count: usize,
  84    last_diagnostics_update_count: usize,
  85    last_file_update_count: usize,
  86    excerpts: Vec<ExcerptId>,
  87    _subscriptions: [gpui::Subscription; 2],
  88}
  89
  90#[derive(Clone, Default)]
  91pub struct MultiBufferSnapshot {
  92    singleton: bool,
  93    excerpts: SumTree<Excerpt>,
  94    parse_count: usize,
  95    diagnostics_update_count: usize,
  96    trailing_excerpt_update_count: usize,
  97    is_dirty: bool,
  98    has_conflict: bool,
  99}
 100
 101pub struct ExcerptBoundary {
 102    pub row: u32,
 103    pub buffer: BufferSnapshot,
 104    pub range: Range<text::Anchor>,
 105    pub starts_new_buffer: bool,
 106}
 107
 108#[derive(Clone)]
 109struct Excerpt {
 110    id: ExcerptId,
 111    buffer_id: usize,
 112    buffer: BufferSnapshot,
 113    range: Range<text::Anchor>,
 114    max_buffer_row: u32,
 115    text_summary: TextSummary,
 116    has_trailing_newline: bool,
 117}
 118
 119#[derive(Clone, Debug, Default)]
 120struct ExcerptSummary {
 121    excerpt_id: ExcerptId,
 122    max_buffer_row: u32,
 123    text: TextSummary,
 124}
 125
 126pub struct MultiBufferRows<'a> {
 127    buffer_row_range: Range<u32>,
 128    excerpts: Cursor<'a, Excerpt, Point>,
 129}
 130
 131pub struct MultiBufferChunks<'a> {
 132    range: Range<usize>,
 133    excerpts: Cursor<'a, Excerpt, usize>,
 134    excerpt_chunks: Option<ExcerptChunks<'a>>,
 135    language_aware: bool,
 136}
 137
 138pub struct MultiBufferBytes<'a> {
 139    range: Range<usize>,
 140    excerpts: Cursor<'a, Excerpt, usize>,
 141    excerpt_bytes: Option<ExcerptBytes<'a>>,
 142    chunk: &'a [u8],
 143}
 144
 145struct ExcerptChunks<'a> {
 146    content_chunks: BufferChunks<'a>,
 147    footer_height: usize,
 148}
 149
 150struct ExcerptBytes<'a> {
 151    content_bytes: language::rope::Bytes<'a>,
 152    footer_height: usize,
 153}
 154
 155impl MultiBuffer {
 156    pub fn new(replica_id: ReplicaId) -> Self {
 157        Self {
 158            snapshot: Default::default(),
 159            buffers: Default::default(),
 160            subscriptions: Default::default(),
 161            singleton: false,
 162            replica_id,
 163            history: History {
 164                next_transaction_id: Default::default(),
 165                undo_stack: Default::default(),
 166                redo_stack: Default::default(),
 167                transaction_depth: 0,
 168                group_interval: Duration::from_millis(300),
 169            },
 170        }
 171    }
 172
 173    pub fn singleton(buffer: ModelHandle<Buffer>, cx: &mut ModelContext<Self>) -> Self {
 174        let mut this = Self::new(buffer.read(cx).replica_id());
 175        this.singleton = true;
 176        this.push_excerpt(buffer, text::Anchor::min()..text::Anchor::max(), cx);
 177        this.snapshot.borrow_mut().singleton = true;
 178        this
 179    }
 180
 181    #[cfg(any(test, feature = "test-support"))]
 182    pub fn build_simple(text: &str, cx: &mut gpui::MutableAppContext) -> ModelHandle<Self> {
 183        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx));
 184        cx.add_model(|cx| Self::singleton(buffer, cx))
 185    }
 186
 187    #[cfg(any(test, feature = "test-support"))]
 188    pub fn build_random(
 189        rng: &mut impl rand::Rng,
 190        cx: &mut gpui::MutableAppContext,
 191    ) -> ModelHandle<Self> {
 192        cx.add_model(|cx| {
 193            let mut multibuffer = MultiBuffer::new(0);
 194            let mutation_count = rng.gen_range(1..=5);
 195            multibuffer.randomly_edit_excerpts(rng, mutation_count, cx);
 196            multibuffer
 197        })
 198    }
 199
 200    pub fn replica_id(&self) -> ReplicaId {
 201        self.replica_id
 202    }
 203
 204    pub fn snapshot(&self, cx: &AppContext) -> MultiBufferSnapshot {
 205        self.sync(cx);
 206        self.snapshot.borrow().clone()
 207    }
 208
 209    pub fn read(&self, cx: &AppContext) -> Ref<MultiBufferSnapshot> {
 210        self.sync(cx);
 211        self.snapshot.borrow()
 212    }
 213
 214    pub fn as_singleton(&self) -> Option<ModelHandle<Buffer>> {
 215        if self.singleton {
 216            return Some(
 217                self.buffers
 218                    .borrow()
 219                    .values()
 220                    .next()
 221                    .unwrap()
 222                    .buffer
 223                    .clone(),
 224            );
 225        } else {
 226            None
 227        }
 228    }
 229
 230    pub fn subscribe(&mut self) -> Subscription {
 231        self.subscriptions.subscribe()
 232    }
 233
 234    pub fn edit<I, S, T>(&mut self, ranges: I, new_text: T, cx: &mut ModelContext<Self>)
 235    where
 236        I: IntoIterator<Item = Range<S>>,
 237        S: ToOffset,
 238        T: Into<String>,
 239    {
 240        self.edit_internal(ranges, new_text, false, cx)
 241    }
 242
 243    pub fn edit_with_autoindent<I, S, T>(
 244        &mut self,
 245        ranges: I,
 246        new_text: T,
 247        cx: &mut ModelContext<Self>,
 248    ) where
 249        I: IntoIterator<Item = Range<S>>,
 250        S: ToOffset,
 251        T: Into<String>,
 252    {
 253        self.edit_internal(ranges, new_text, true, cx)
 254    }
 255
 256    pub fn edit_internal<I, S, T>(
 257        &mut self,
 258        ranges_iter: I,
 259        new_text: T,
 260        autoindent: bool,
 261        cx: &mut ModelContext<Self>,
 262    ) where
 263        I: IntoIterator<Item = Range<S>>,
 264        S: ToOffset,
 265        T: Into<String>,
 266    {
 267        if self.buffers.borrow().is_empty() {
 268            return;
 269        }
 270
 271        if let Some(buffer) = self.as_singleton() {
 272            let snapshot = self.read(cx);
 273            let ranges = ranges_iter
 274                .into_iter()
 275                .map(|range| range.start.to_offset(&snapshot)..range.end.to_offset(&snapshot));
 276            return buffer.update(cx, |buffer, cx| {
 277                if autoindent {
 278                    buffer.edit_with_autoindent(ranges, new_text, cx);
 279                } else {
 280                    buffer.edit(ranges, new_text, cx);
 281                }
 282            });
 283        }
 284
 285        let snapshot = self.read(cx);
 286        let mut buffer_edits: HashMap<usize, Vec<(Range<usize>, bool)>> = Default::default();
 287        let mut cursor = snapshot.excerpts.cursor::<usize>();
 288        for range in ranges_iter {
 289            let start = range.start.to_offset(&snapshot);
 290            let end = range.end.to_offset(&snapshot);
 291            cursor.seek(&start, Bias::Right, &());
 292            if cursor.item().is_none() && start == *cursor.start() {
 293                cursor.prev(&());
 294            }
 295            let start_excerpt = cursor.item().expect("start offset out of bounds");
 296            let start_overshoot = start - cursor.start();
 297            let buffer_start =
 298                start_excerpt.range.start.to_offset(&start_excerpt.buffer) + start_overshoot;
 299
 300            cursor.seek(&end, Bias::Right, &());
 301            if cursor.item().is_none() && end == *cursor.start() {
 302                cursor.prev(&());
 303            }
 304            let end_excerpt = cursor.item().expect("end offset out of bounds");
 305            let end_overshoot = end - cursor.start();
 306            let buffer_end = end_excerpt.range.start.to_offset(&end_excerpt.buffer) + end_overshoot;
 307
 308            if start_excerpt.id == end_excerpt.id {
 309                buffer_edits
 310                    .entry(start_excerpt.buffer_id)
 311                    .or_insert(Vec::new())
 312                    .push((buffer_start..buffer_end, true));
 313            } else {
 314                let start_excerpt_range =
 315                    buffer_start..start_excerpt.range.end.to_offset(&start_excerpt.buffer);
 316                let end_excerpt_range =
 317                    end_excerpt.range.start.to_offset(&end_excerpt.buffer)..buffer_end;
 318                buffer_edits
 319                    .entry(start_excerpt.buffer_id)
 320                    .or_insert(Vec::new())
 321                    .push((start_excerpt_range, true));
 322                buffer_edits
 323                    .entry(end_excerpt.buffer_id)
 324                    .or_insert(Vec::new())
 325                    .push((end_excerpt_range, false));
 326
 327                cursor.seek(&start, Bias::Right, &());
 328                cursor.next(&());
 329                while let Some(excerpt) = cursor.item() {
 330                    if excerpt.id == end_excerpt.id {
 331                        break;
 332                    }
 333                    buffer_edits
 334                        .entry(excerpt.buffer_id)
 335                        .or_insert(Vec::new())
 336                        .push((excerpt.range.to_offset(&excerpt.buffer), false));
 337                    cursor.next(&());
 338                }
 339            }
 340        }
 341
 342        let new_text = new_text.into();
 343        for (buffer_id, mut edits) in buffer_edits {
 344            edits.sort_unstable_by_key(|(range, _)| range.start);
 345            self.buffers.borrow()[&buffer_id]
 346                .buffer
 347                .update(cx, |buffer, cx| {
 348                    let mut edits = edits.into_iter().peekable();
 349                    let mut insertions = Vec::new();
 350                    let mut deletions = Vec::new();
 351                    while let Some((mut range, mut is_insertion)) = edits.next() {
 352                        while let Some((next_range, next_is_insertion)) = edits.peek() {
 353                            if range.end >= next_range.start {
 354                                range.end = cmp::max(next_range.end, range.end);
 355                                is_insertion |= *next_is_insertion;
 356                                edits.next();
 357                            } else {
 358                                break;
 359                            }
 360                        }
 361
 362                        if is_insertion {
 363                            insertions.push(
 364                                buffer.anchor_before(range.start)..buffer.anchor_before(range.end),
 365                            );
 366                        } else if !range.is_empty() {
 367                            deletions.push(
 368                                buffer.anchor_before(range.start)..buffer.anchor_before(range.end),
 369                            );
 370                        }
 371                    }
 372
 373                    if autoindent {
 374                        buffer.edit_with_autoindent(deletions, "", cx);
 375                        buffer.edit_with_autoindent(insertions, new_text.clone(), cx);
 376                    } else {
 377                        buffer.edit(deletions, "", cx);
 378                        buffer.edit(insertions, new_text.clone(), cx);
 379                    }
 380                })
 381        }
 382    }
 383
 384    pub fn start_transaction(&mut self, cx: &mut ModelContext<Self>) -> Option<TransactionId> {
 385        self.start_transaction_at(Instant::now(), cx)
 386    }
 387
 388    pub(crate) fn start_transaction_at(
 389        &mut self,
 390        now: Instant,
 391        cx: &mut ModelContext<Self>,
 392    ) -> Option<TransactionId> {
 393        if let Some(buffer) = self.as_singleton() {
 394            return buffer.update(cx, |buffer, _| buffer.start_transaction_at(now));
 395        }
 396
 397        for BufferState { buffer, .. } in self.buffers.borrow().values() {
 398            buffer.update(cx, |buffer, _| buffer.start_transaction_at(now));
 399        }
 400        self.history.start_transaction(now)
 401    }
 402
 403    pub fn end_transaction(&mut self, cx: &mut ModelContext<Self>) -> Option<TransactionId> {
 404        self.end_transaction_at(Instant::now(), cx)
 405    }
 406
 407    pub(crate) fn end_transaction_at(
 408        &mut self,
 409        now: Instant,
 410        cx: &mut ModelContext<Self>,
 411    ) -> Option<TransactionId> {
 412        if let Some(buffer) = self.as_singleton() {
 413            return buffer.update(cx, |buffer, cx| buffer.end_transaction_at(now, cx));
 414        }
 415
 416        let mut buffer_transactions = HashSet::default();
 417        for BufferState { buffer, .. } in self.buffers.borrow().values() {
 418            if let Some(transaction_id) =
 419                buffer.update(cx, |buffer, cx| buffer.end_transaction_at(now, cx))
 420            {
 421                buffer_transactions.insert((buffer.id(), transaction_id));
 422            }
 423        }
 424
 425        if self.history.end_transaction(now, buffer_transactions) {
 426            let transaction_id = self.history.group().unwrap();
 427            Some(transaction_id)
 428        } else {
 429            None
 430        }
 431    }
 432
 433    pub fn finalize_last_transaction(&mut self, cx: &mut ModelContext<Self>) {
 434        for BufferState { buffer, .. } in self.buffers.borrow().values() {
 435            buffer.update(cx, |buffer, _| {
 436                buffer.finalize_last_transaction();
 437            });
 438        }
 439    }
 440
 441    pub fn set_active_selections(
 442        &mut self,
 443        selections: &[Selection<Anchor>],
 444        cx: &mut ModelContext<Self>,
 445    ) {
 446        let mut selections_by_buffer: HashMap<usize, Vec<Selection<text::Anchor>>> =
 447            Default::default();
 448        let snapshot = self.read(cx);
 449        let mut cursor = snapshot.excerpts.cursor::<Option<&ExcerptId>>();
 450        for selection in selections {
 451            cursor.seek(&Some(&selection.start.excerpt_id), Bias::Left, &());
 452            while let Some(excerpt) = cursor.item() {
 453                if excerpt.id > selection.end.excerpt_id {
 454                    break;
 455                }
 456
 457                let mut start = excerpt.range.start.clone();
 458                let mut end = excerpt.range.end.clone();
 459                if excerpt.id == selection.start.excerpt_id {
 460                    start = selection.start.text_anchor.clone();
 461                }
 462                if excerpt.id == selection.end.excerpt_id {
 463                    end = selection.end.text_anchor.clone();
 464                }
 465                selections_by_buffer
 466                    .entry(excerpt.buffer_id)
 467                    .or_default()
 468                    .push(Selection {
 469                        id: selection.id,
 470                        start,
 471                        end,
 472                        reversed: selection.reversed,
 473                        goal: selection.goal,
 474                    });
 475
 476                cursor.next(&());
 477            }
 478        }
 479
 480        for (buffer_id, buffer_state) in self.buffers.borrow().iter() {
 481            if !selections_by_buffer.contains_key(buffer_id) {
 482                buffer_state
 483                    .buffer
 484                    .update(cx, |buffer, cx| buffer.remove_active_selections(cx));
 485            }
 486        }
 487
 488        for (buffer_id, mut selections) in selections_by_buffer {
 489            self.buffers.borrow()[&buffer_id]
 490                .buffer
 491                .update(cx, |buffer, cx| {
 492                    selections.sort_unstable_by(|a, b| a.start.cmp(&b.start, buffer).unwrap());
 493                    let mut selections = selections.into_iter().peekable();
 494                    let merged_selections = Arc::from_iter(iter::from_fn(|| {
 495                        let mut selection = selections.next()?;
 496                        while let Some(next_selection) = selections.peek() {
 497                            if selection
 498                                .end
 499                                .cmp(&next_selection.start, buffer)
 500                                .unwrap()
 501                                .is_ge()
 502                            {
 503                                let next_selection = selections.next().unwrap();
 504                                if next_selection
 505                                    .end
 506                                    .cmp(&selection.end, buffer)
 507                                    .unwrap()
 508                                    .is_ge()
 509                                {
 510                                    selection.end = next_selection.end;
 511                                }
 512                            } else {
 513                                break;
 514                            }
 515                        }
 516                        Some(selection)
 517                    }));
 518                    buffer.set_active_selections(merged_selections, cx);
 519                });
 520        }
 521    }
 522
 523    pub fn remove_active_selections(&mut self, cx: &mut ModelContext<Self>) {
 524        for buffer in self.buffers.borrow().values() {
 525            buffer
 526                .buffer
 527                .update(cx, |buffer, cx| buffer.remove_active_selections(cx));
 528        }
 529    }
 530
 531    pub fn undo(&mut self, cx: &mut ModelContext<Self>) -> Option<TransactionId> {
 532        if let Some(buffer) = self.as_singleton() {
 533            return buffer.update(cx, |buffer, cx| buffer.undo(cx));
 534        }
 535
 536        while let Some(transaction) = self.history.pop_undo() {
 537            let mut undone = false;
 538            for (buffer_id, buffer_transaction_id) in &transaction.buffer_transactions {
 539                if let Some(BufferState { buffer, .. }) = self.buffers.borrow().get(&buffer_id) {
 540                    undone |= buffer.update(cx, |buf, cx| {
 541                        buf.undo_transaction(*buffer_transaction_id, cx)
 542                    });
 543                }
 544            }
 545
 546            if undone {
 547                return Some(transaction.id);
 548            }
 549        }
 550
 551        None
 552    }
 553
 554    pub fn redo(&mut self, cx: &mut ModelContext<Self>) -> Option<TransactionId> {
 555        if let Some(buffer) = self.as_singleton() {
 556            return buffer.update(cx, |buffer, cx| buffer.redo(cx));
 557        }
 558
 559        while let Some(transaction) = self.history.pop_redo() {
 560            let mut redone = false;
 561            for (buffer_id, buffer_transaction_id) in &transaction.buffer_transactions {
 562                if let Some(BufferState { buffer, .. }) = self.buffers.borrow().get(&buffer_id) {
 563                    redone |= buffer.update(cx, |buf, cx| {
 564                        buf.redo_transaction(*buffer_transaction_id, cx)
 565                    });
 566                }
 567            }
 568
 569            if redone {
 570                return Some(transaction.id);
 571            }
 572        }
 573
 574        None
 575    }
 576
 577    pub fn push_excerpt<O>(
 578        &mut self,
 579        buffer: ModelHandle<Buffer>,
 580        range: Range<O>,
 581        cx: &mut ModelContext<Self>,
 582    ) -> ExcerptId
 583    where
 584        O: text::ToOffset,
 585    {
 586        self.insert_excerpt_after(&ExcerptId::max(), buffer, range, cx)
 587    }
 588
 589    pub fn insert_excerpt_after<O>(
 590        &mut self,
 591        prev_excerpt_id: &ExcerptId,
 592        buffer: ModelHandle<Buffer>,
 593        range: Range<O>,
 594        cx: &mut ModelContext<Self>,
 595    ) -> ExcerptId
 596    where
 597        O: text::ToOffset,
 598    {
 599        assert_eq!(self.history.transaction_depth, 0);
 600        self.sync(cx);
 601
 602        let buffer_id = buffer.id();
 603        let buffer_snapshot = buffer.read(cx).snapshot();
 604        let range =
 605            buffer_snapshot.anchor_before(&range.start)..buffer_snapshot.anchor_after(&range.end);
 606        let mut snapshot = self.snapshot.borrow_mut();
 607        let mut cursor = snapshot.excerpts.cursor::<Option<&ExcerptId>>();
 608        let mut new_excerpts = cursor.slice(&Some(prev_excerpt_id), Bias::Right, &());
 609
 610        let mut prev_id = ExcerptId::min();
 611        let edit_start = new_excerpts.summary().text.bytes;
 612        new_excerpts.update_last(
 613            |excerpt| {
 614                excerpt.has_trailing_newline = true;
 615                prev_id = excerpt.id.clone();
 616            },
 617            &(),
 618        );
 619
 620        let mut next_id = ExcerptId::max();
 621        if let Some(next_excerpt) = cursor.item() {
 622            next_id = next_excerpt.id.clone();
 623        }
 624
 625        let id = ExcerptId::between(&prev_id, &next_id);
 626
 627        let mut buffers = self.buffers.borrow_mut();
 628        let buffer_state = buffers.entry(buffer_id).or_insert_with(|| BufferState {
 629            last_version: buffer_snapshot.version().clone(),
 630            last_parse_count: buffer_snapshot.parse_count(),
 631            last_selections_update_count: buffer_snapshot.selections_update_count(),
 632            last_diagnostics_update_count: buffer_snapshot.diagnostics_update_count(),
 633            last_file_update_count: buffer_snapshot.file_update_count(),
 634            excerpts: Default::default(),
 635            _subscriptions: [
 636                cx.observe(&buffer, |_, _, cx| cx.notify()),
 637                cx.subscribe(&buffer, Self::on_buffer_event),
 638            ],
 639            buffer,
 640        });
 641        if let Err(ix) = buffer_state.excerpts.binary_search(&id) {
 642            buffer_state.excerpts.insert(ix, id.clone());
 643        }
 644
 645        let excerpt = Excerpt::new(
 646            id.clone(),
 647            buffer_id,
 648            buffer_snapshot,
 649            range,
 650            cursor.item().is_some(),
 651        );
 652        new_excerpts.push(excerpt, &());
 653        let edit_end = new_excerpts.summary().text.bytes;
 654
 655        let suffix = cursor.suffix(&());
 656        let changed_trailing_excerpt = suffix.is_empty();
 657        new_excerpts.push_tree(suffix, &());
 658        drop(cursor);
 659        snapshot.excerpts = new_excerpts;
 660        if changed_trailing_excerpt {
 661            snapshot.trailing_excerpt_update_count += 1;
 662        }
 663
 664        self.subscriptions.publish_mut([Edit {
 665            old: edit_start..edit_start,
 666            new: edit_start..edit_end,
 667        }]);
 668
 669        cx.notify();
 670        id
 671    }
 672
 673    pub fn excerpt_ids_for_buffer(&self, buffer: &ModelHandle<Buffer>) -> Vec<ExcerptId> {
 674        self.buffers
 675            .borrow()
 676            .get(&buffer.id())
 677            .map_or(Vec::new(), |state| state.excerpts.clone())
 678    }
 679
 680    pub fn excerpted_buffers<'a, T: ToOffset>(
 681        &'a self,
 682        range: Range<T>,
 683        cx: &AppContext,
 684    ) -> Vec<(ModelHandle<Buffer>, Range<usize>)> {
 685        let snapshot = self.snapshot(cx);
 686        let start = range.start.to_offset(&snapshot);
 687        let end = range.end.to_offset(&snapshot);
 688
 689        let mut result = Vec::new();
 690        let mut cursor = snapshot.excerpts.cursor::<usize>();
 691        cursor.seek(&start, Bias::Right, &());
 692        while let Some(excerpt) = cursor.item() {
 693            if *cursor.start() > end {
 694                break;
 695            }
 696
 697            let mut end_before_newline = cursor.end(&());
 698            if excerpt.has_trailing_newline {
 699                end_before_newline -= 1;
 700            }
 701            let excerpt_start = excerpt.range.start.to_offset(&excerpt.buffer);
 702            let start = excerpt_start + (cmp::max(start, *cursor.start()) - *cursor.start());
 703            let end = excerpt_start + (cmp::min(end, end_before_newline) - *cursor.start());
 704            let buffer = self.buffers.borrow()[&excerpt.buffer_id].buffer.clone();
 705            result.push((buffer, start..end));
 706            cursor.next(&());
 707        }
 708
 709        result
 710    }
 711
 712    pub fn remove_excerpts<'a>(
 713        &mut self,
 714        excerpt_ids: impl IntoIterator<Item = &'a ExcerptId>,
 715        cx: &mut ModelContext<Self>,
 716    ) {
 717        let mut buffers = self.buffers.borrow_mut();
 718        let mut snapshot = self.snapshot.borrow_mut();
 719        let mut new_excerpts = SumTree::new();
 720        let mut cursor = snapshot.excerpts.cursor::<(Option<&ExcerptId>, usize)>();
 721        let mut edits = Vec::new();
 722        let mut excerpt_ids = excerpt_ids.into_iter().peekable();
 723
 724        while let Some(mut excerpt_id) = excerpt_ids.next() {
 725            // Seek to the next excerpt to remove, preserving any preceding excerpts.
 726            new_excerpts.push_tree(cursor.slice(&Some(excerpt_id), Bias::Left, &()), &());
 727            if let Some(mut excerpt) = cursor.item() {
 728                if excerpt.id != *excerpt_id {
 729                    continue;
 730                }
 731                let mut old_start = cursor.start().1;
 732
 733                // Skip over the removed excerpt.
 734                loop {
 735                    if let Some(buffer_state) = buffers.get_mut(&excerpt.buffer_id) {
 736                        buffer_state.excerpts.retain(|id| id != excerpt_id);
 737                        if buffer_state.excerpts.is_empty() {
 738                            buffers.remove(&excerpt.buffer_id);
 739                        }
 740                    }
 741                    cursor.next(&());
 742
 743                    // Skip over any subsequent excerpts that are also removed.
 744                    if let Some(&next_excerpt_id) = excerpt_ids.peek() {
 745                        if let Some(next_excerpt) = cursor.item() {
 746                            if next_excerpt.id == *next_excerpt_id {
 747                                excerpt = next_excerpt;
 748                                excerpt_id = excerpt_ids.next().unwrap();
 749                                continue;
 750                            }
 751                        }
 752                    }
 753
 754                    break;
 755                }
 756
 757                // When removing the last excerpt, remove the trailing newline from
 758                // the previous excerpt.
 759                if cursor.item().is_none() && old_start > 0 {
 760                    old_start -= 1;
 761                    new_excerpts.update_last(|e| e.has_trailing_newline = false, &());
 762                }
 763
 764                // Push an edit for the removal of this run of excerpts.
 765                let old_end = cursor.start().1;
 766                let new_start = new_excerpts.summary().text.bytes;
 767                edits.push(Edit {
 768                    old: old_start..old_end,
 769                    new: new_start..new_start,
 770                });
 771            }
 772        }
 773        let suffix = cursor.suffix(&());
 774        let changed_trailing_excerpt = suffix.is_empty();
 775        new_excerpts.push_tree(suffix, &());
 776        drop(cursor);
 777        snapshot.excerpts = new_excerpts;
 778        if changed_trailing_excerpt {
 779            snapshot.trailing_excerpt_update_count += 1;
 780        }
 781
 782        self.subscriptions.publish_mut(edits);
 783        cx.notify();
 784    }
 785
 786    pub fn text_anchor_for_position<'a, T: ToOffset>(
 787        &'a self,
 788        position: T,
 789        cx: &AppContext,
 790    ) -> (ModelHandle<Buffer>, language::Anchor) {
 791        let snapshot = self.read(cx);
 792        let anchor = snapshot.anchor_before(position);
 793        (
 794            self.buffers.borrow()[&anchor.buffer_id].buffer.clone(),
 795            anchor.text_anchor,
 796        )
 797    }
 798
 799    fn on_buffer_event(
 800        &mut self,
 801        _: ModelHandle<Buffer>,
 802        event: &Event,
 803        cx: &mut ModelContext<Self>,
 804    ) {
 805        cx.emit(event.clone());
 806    }
 807
 808    pub fn format(&mut self, cx: &mut ModelContext<Self>) -> Task<Result<()>> {
 809        let mut format_tasks = Vec::new();
 810        for BufferState { buffer, .. } in self.buffers.borrow().values() {
 811            format_tasks.push(buffer.update(cx, |buffer, cx| buffer.format(cx)));
 812        }
 813
 814        cx.spawn(|_, _| async move {
 815            for format in format_tasks {
 816                format.await?;
 817            }
 818            Ok(())
 819        })
 820    }
 821
 822    pub fn save(&mut self, cx: &mut ModelContext<Self>) -> Task<Result<()>> {
 823        let mut save_tasks = Vec::new();
 824        for BufferState { buffer, .. } in self.buffers.borrow().values() {
 825            save_tasks.push(buffer.update(cx, |buffer, cx| buffer.save(cx)));
 826        }
 827
 828        cx.spawn(|_, _| async move {
 829            for save in save_tasks {
 830                save.await?;
 831            }
 832            Ok(())
 833        })
 834    }
 835
 836    pub fn is_completion_trigger<T>(&self, position: T, text: &str, cx: &AppContext) -> bool
 837    where
 838        T: ToOffset,
 839    {
 840        let mut chars = text.chars();
 841        let char = if let Some(char) = chars.next() {
 842            char
 843        } else {
 844            return false;
 845        };
 846        if chars.next().is_some() {
 847            return false;
 848        }
 849
 850        if char.is_alphanumeric() || char == '_' {
 851            return true;
 852        }
 853
 854        let snapshot = self.snapshot(cx);
 855        let anchor = snapshot.anchor_before(position);
 856        let buffer = self.buffers.borrow()[&anchor.buffer_id].buffer.clone();
 857        buffer
 858            .read(cx)
 859            .completion_triggers()
 860            .iter()
 861            .any(|string| string == text)
 862    }
 863
 864    pub fn language<'a>(&self, cx: &'a AppContext) -> Option<&'a Arc<Language>> {
 865        self.buffers
 866            .borrow()
 867            .values()
 868            .next()
 869            .and_then(|state| state.buffer.read(cx).language())
 870    }
 871
 872    pub fn file<'a>(&self, cx: &'a AppContext) -> Option<&'a dyn File> {
 873        self.as_singleton()?.read(cx).file()
 874    }
 875
 876    #[cfg(test)]
 877    pub fn is_parsing(&self, cx: &AppContext) -> bool {
 878        self.as_singleton().unwrap().read(cx).is_parsing()
 879    }
 880
 881    fn sync(&self, cx: &AppContext) {
 882        let mut snapshot = self.snapshot.borrow_mut();
 883        let mut excerpts_to_edit = Vec::new();
 884        let mut reparsed = false;
 885        let mut diagnostics_updated = false;
 886        let mut is_dirty = false;
 887        let mut has_conflict = false;
 888        let mut buffers = self.buffers.borrow_mut();
 889        for buffer_state in buffers.values_mut() {
 890            let buffer = buffer_state.buffer.read(cx);
 891            let version = buffer.version();
 892            let parse_count = buffer.parse_count();
 893            let selections_update_count = buffer.selections_update_count();
 894            let diagnostics_update_count = buffer.diagnostics_update_count();
 895            let file_update_count = buffer.file_update_count();
 896
 897            let buffer_edited = version.changed_since(&buffer_state.last_version);
 898            let buffer_reparsed = parse_count > buffer_state.last_parse_count;
 899            let buffer_selections_updated =
 900                selections_update_count > buffer_state.last_selections_update_count;
 901            let buffer_diagnostics_updated =
 902                diagnostics_update_count > buffer_state.last_diagnostics_update_count;
 903            let buffer_file_updated = file_update_count > buffer_state.last_file_update_count;
 904            if buffer_edited
 905                || buffer_reparsed
 906                || buffer_selections_updated
 907                || buffer_diagnostics_updated
 908                || buffer_file_updated
 909            {
 910                buffer_state.last_version = version;
 911                buffer_state.last_parse_count = parse_count;
 912                buffer_state.last_selections_update_count = selections_update_count;
 913                buffer_state.last_diagnostics_update_count = diagnostics_update_count;
 914                buffer_state.last_file_update_count = file_update_count;
 915                excerpts_to_edit.extend(
 916                    buffer_state
 917                        .excerpts
 918                        .iter()
 919                        .map(|excerpt_id| (excerpt_id, buffer_state.buffer.clone(), buffer_edited)),
 920                );
 921            }
 922
 923            reparsed |= buffer_reparsed;
 924            diagnostics_updated |= buffer_diagnostics_updated;
 925            is_dirty |= buffer.is_dirty();
 926            has_conflict |= buffer.has_conflict();
 927        }
 928        if reparsed {
 929            snapshot.parse_count += 1;
 930        }
 931        if diagnostics_updated {
 932            snapshot.diagnostics_update_count += 1;
 933        }
 934        snapshot.is_dirty = is_dirty;
 935        snapshot.has_conflict = has_conflict;
 936
 937        excerpts_to_edit.sort_unstable_by_key(|(excerpt_id, _, _)| *excerpt_id);
 938
 939        let mut edits = Vec::new();
 940        let mut new_excerpts = SumTree::new();
 941        let mut cursor = snapshot.excerpts.cursor::<(Option<&ExcerptId>, usize)>();
 942
 943        for (id, buffer, buffer_edited) in excerpts_to_edit {
 944            new_excerpts.push_tree(cursor.slice(&Some(id), Bias::Left, &()), &());
 945            let old_excerpt = cursor.item().unwrap();
 946            let buffer_id = buffer.id();
 947            let buffer = buffer.read(cx);
 948
 949            let mut new_excerpt;
 950            if buffer_edited {
 951                edits.extend(
 952                    buffer
 953                        .edits_since_in_range::<usize>(
 954                            old_excerpt.buffer.version(),
 955                            old_excerpt.range.clone(),
 956                        )
 957                        .map(|mut edit| {
 958                            let excerpt_old_start = cursor.start().1;
 959                            let excerpt_new_start = new_excerpts.summary().text.bytes;
 960                            edit.old.start += excerpt_old_start;
 961                            edit.old.end += excerpt_old_start;
 962                            edit.new.start += excerpt_new_start;
 963                            edit.new.end += excerpt_new_start;
 964                            edit
 965                        }),
 966                );
 967
 968                new_excerpt = Excerpt::new(
 969                    id.clone(),
 970                    buffer_id,
 971                    buffer.snapshot(),
 972                    old_excerpt.range.clone(),
 973                    old_excerpt.has_trailing_newline,
 974                );
 975            } else {
 976                new_excerpt = old_excerpt.clone();
 977                new_excerpt.buffer = buffer.snapshot();
 978            }
 979
 980            new_excerpts.push(new_excerpt, &());
 981            cursor.next(&());
 982        }
 983        new_excerpts.push_tree(cursor.suffix(&()), &());
 984
 985        drop(cursor);
 986        snapshot.excerpts = new_excerpts;
 987
 988        self.subscriptions.publish(edits);
 989    }
 990}
 991
 992#[cfg(any(test, feature = "test-support"))]
 993impl MultiBuffer {
 994    pub fn randomly_edit(
 995        &mut self,
 996        rng: &mut impl rand::Rng,
 997        count: usize,
 998        cx: &mut ModelContext<Self>,
 999    ) {
1000        use text::RandomCharIter;
1001
1002        let snapshot = self.read(cx);
1003        let mut old_ranges: Vec<Range<usize>> = Vec::new();
1004        for _ in 0..count {
1005            let last_end = old_ranges.last().map_or(0, |last_range| last_range.end + 1);
1006            if last_end > snapshot.len() {
1007                break;
1008            }
1009            let end_ix = snapshot.clip_offset(rng.gen_range(0..=last_end), Bias::Right);
1010            let start_ix = snapshot.clip_offset(rng.gen_range(0..=end_ix), Bias::Left);
1011            old_ranges.push(start_ix..end_ix);
1012        }
1013        let new_text_len = rng.gen_range(0..10);
1014        let new_text: String = RandomCharIter::new(&mut *rng).take(new_text_len).collect();
1015        log::info!("mutating multi-buffer at {:?}: {:?}", old_ranges, new_text);
1016        drop(snapshot);
1017
1018        self.edit(old_ranges.iter().cloned(), new_text.as_str(), cx);
1019    }
1020
1021    pub fn randomly_edit_excerpts(
1022        &mut self,
1023        rng: &mut impl rand::Rng,
1024        mutation_count: usize,
1025        cx: &mut ModelContext<Self>,
1026    ) {
1027        use rand::prelude::*;
1028        use std::env;
1029        use text::RandomCharIter;
1030
1031        let max_excerpts = env::var("MAX_EXCERPTS")
1032            .map(|i| i.parse().expect("invalid `MAX_EXCERPTS` variable"))
1033            .unwrap_or(5);
1034
1035        let mut buffers = Vec::new();
1036        for _ in 0..mutation_count {
1037            let excerpt_ids = self
1038                .buffers
1039                .borrow()
1040                .values()
1041                .flat_map(|b| &b.excerpts)
1042                .cloned()
1043                .collect::<Vec<_>>();
1044            if excerpt_ids.len() == 0 || (rng.gen() && excerpt_ids.len() < max_excerpts) {
1045                let buffer_handle = if rng.gen() || self.buffers.borrow().is_empty() {
1046                    let text = RandomCharIter::new(&mut *rng).take(10).collect::<String>();
1047                    buffers.push(cx.add_model(|cx| Buffer::new(0, text, cx)));
1048                    let buffer = buffers.last().unwrap();
1049                    log::info!(
1050                        "Creating new buffer {} with text: {:?}",
1051                        buffer.id(),
1052                        buffer.read(cx).text()
1053                    );
1054                    buffers.last().unwrap().clone()
1055                } else {
1056                    self.buffers
1057                        .borrow()
1058                        .values()
1059                        .choose(rng)
1060                        .unwrap()
1061                        .buffer
1062                        .clone()
1063                };
1064
1065                let buffer = buffer_handle.read(cx);
1066                let end_ix = buffer.clip_offset(rng.gen_range(0..=buffer.len()), Bias::Right);
1067                let start_ix = buffer.clip_offset(rng.gen_range(0..=end_ix), Bias::Left);
1068                log::info!(
1069                    "Inserting excerpt from buffer {} and range {:?}: {:?}",
1070                    buffer_handle.id(),
1071                    start_ix..end_ix,
1072                    &buffer.text()[start_ix..end_ix]
1073                );
1074
1075                let excerpt_id = self.push_excerpt(buffer_handle.clone(), start_ix..end_ix, cx);
1076                log::info!("Inserted with id: {:?}", excerpt_id);
1077            } else {
1078                let remove_count = rng.gen_range(1..=excerpt_ids.len());
1079                let mut excerpts_to_remove = excerpt_ids
1080                    .choose_multiple(rng, remove_count)
1081                    .cloned()
1082                    .collect::<Vec<_>>();
1083                excerpts_to_remove.sort();
1084                log::info!("Removing excerpts {:?}", excerpts_to_remove);
1085                self.remove_excerpts(&excerpts_to_remove, cx);
1086            }
1087        }
1088    }
1089
1090    pub fn randomly_mutate(
1091        &mut self,
1092        rng: &mut impl rand::Rng,
1093        mutation_count: usize,
1094        cx: &mut ModelContext<Self>,
1095    ) {
1096        if rng.gen_bool(0.7) || self.singleton {
1097            self.randomly_edit(rng, mutation_count, cx);
1098        } else {
1099            self.randomly_edit_excerpts(rng, mutation_count, cx);
1100        }
1101    }
1102}
1103
1104impl Entity for MultiBuffer {
1105    type Event = language::Event;
1106}
1107
1108impl MultiBufferSnapshot {
1109    pub fn text(&self) -> String {
1110        self.chunks(0..self.len(), false)
1111            .map(|chunk| chunk.text)
1112            .collect()
1113    }
1114
1115    pub fn reversed_chars_at<'a, T: ToOffset>(
1116        &'a self,
1117        position: T,
1118    ) -> impl Iterator<Item = char> + 'a {
1119        let mut offset = position.to_offset(self);
1120        let mut cursor = self.excerpts.cursor::<usize>();
1121        cursor.seek(&offset, Bias::Left, &());
1122        let mut excerpt_chunks = cursor.item().map(|excerpt| {
1123            let end_before_footer = cursor.start() + excerpt.text_summary.bytes;
1124            let start = excerpt.range.start.to_offset(&excerpt.buffer);
1125            let end = start + (cmp::min(offset, end_before_footer) - cursor.start());
1126            excerpt.buffer.reversed_chunks_in_range(start..end)
1127        });
1128        iter::from_fn(move || {
1129            if offset == *cursor.start() {
1130                cursor.prev(&());
1131                let excerpt = cursor.item()?;
1132                excerpt_chunks = Some(
1133                    excerpt
1134                        .buffer
1135                        .reversed_chunks_in_range(excerpt.range.clone()),
1136                );
1137            }
1138
1139            let excerpt = cursor.item().unwrap();
1140            if offset == cursor.end(&()) && excerpt.has_trailing_newline {
1141                offset -= 1;
1142                Some("\n")
1143            } else {
1144                let chunk = excerpt_chunks.as_mut().unwrap().next().unwrap();
1145                offset -= chunk.len();
1146                Some(chunk)
1147            }
1148        })
1149        .flat_map(|c| c.chars().rev())
1150    }
1151
1152    pub fn chars_at<'a, T: ToOffset>(&'a self, position: T) -> impl Iterator<Item = char> + 'a {
1153        let offset = position.to_offset(self);
1154        self.text_for_range(offset..self.len())
1155            .flat_map(|chunk| chunk.chars())
1156    }
1157
1158    pub fn text_for_range<'a, T: ToOffset>(
1159        &'a self,
1160        range: Range<T>,
1161    ) -> impl Iterator<Item = &'a str> {
1162        self.chunks(range, false).map(|chunk| chunk.text)
1163    }
1164
1165    pub fn is_line_blank(&self, row: u32) -> bool {
1166        self.text_for_range(Point::new(row, 0)..Point::new(row, self.line_len(row)))
1167            .all(|chunk| chunk.matches(|c: char| !c.is_whitespace()).next().is_none())
1168    }
1169
1170    pub fn contains_str_at<T>(&self, position: T, needle: &str) -> bool
1171    where
1172        T: ToOffset,
1173    {
1174        let position = position.to_offset(self);
1175        position == self.clip_offset(position, Bias::Left)
1176            && self
1177                .bytes_in_range(position..self.len())
1178                .flatten()
1179                .copied()
1180                .take(needle.len())
1181                .eq(needle.bytes())
1182    }
1183
1184    pub fn surrounding_word<T: ToOffset>(&self, start: T) -> (Range<usize>, Option<CharKind>) {
1185        let mut start = start.to_offset(self);
1186        let mut end = start;
1187        let mut next_chars = self.chars_at(start).peekable();
1188        let mut prev_chars = self.reversed_chars_at(start).peekable();
1189        let word_kind = cmp::max(
1190            prev_chars.peek().copied().map(char_kind),
1191            next_chars.peek().copied().map(char_kind),
1192        );
1193
1194        for ch in prev_chars {
1195            if Some(char_kind(ch)) == word_kind {
1196                start -= ch.len_utf8();
1197            } else {
1198                break;
1199            }
1200        }
1201
1202        for ch in next_chars {
1203            if Some(char_kind(ch)) == word_kind {
1204                end += ch.len_utf8();
1205            } else {
1206                break;
1207            }
1208        }
1209
1210        (start..end, word_kind)
1211    }
1212
1213    fn as_singleton(&self) -> Option<&Excerpt> {
1214        if self.singleton {
1215            self.excerpts.iter().next()
1216        } else {
1217            None
1218        }
1219    }
1220
1221    pub fn len(&self) -> usize {
1222        self.excerpts.summary().text.bytes
1223    }
1224
1225    pub fn max_buffer_row(&self) -> u32 {
1226        self.excerpts.summary().max_buffer_row
1227    }
1228
1229    pub fn clip_offset(&self, offset: usize, bias: Bias) -> usize {
1230        if let Some(excerpt) = self.as_singleton() {
1231            return excerpt.buffer.clip_offset(offset, bias);
1232        }
1233
1234        let mut cursor = self.excerpts.cursor::<usize>();
1235        cursor.seek(&offset, Bias::Right, &());
1236        let overshoot = if let Some(excerpt) = cursor.item() {
1237            let excerpt_start = excerpt.range.start.to_offset(&excerpt.buffer);
1238            let buffer_offset = excerpt
1239                .buffer
1240                .clip_offset(excerpt_start + (offset - cursor.start()), bias);
1241            buffer_offset.saturating_sub(excerpt_start)
1242        } else {
1243            0
1244        };
1245        cursor.start() + overshoot
1246    }
1247
1248    pub fn clip_point(&self, point: Point, bias: Bias) -> Point {
1249        if let Some(excerpt) = self.as_singleton() {
1250            return excerpt.buffer.clip_point(point, bias);
1251        }
1252
1253        let mut cursor = self.excerpts.cursor::<Point>();
1254        cursor.seek(&point, Bias::Right, &());
1255        let overshoot = if let Some(excerpt) = cursor.item() {
1256            let excerpt_start = excerpt.range.start.to_point(&excerpt.buffer);
1257            let buffer_point = excerpt
1258                .buffer
1259                .clip_point(excerpt_start + (point - cursor.start()), bias);
1260            buffer_point.saturating_sub(excerpt_start)
1261        } else {
1262            Point::zero()
1263        };
1264        *cursor.start() + overshoot
1265    }
1266
1267    pub fn clip_point_utf16(&self, point: PointUtf16, bias: Bias) -> PointUtf16 {
1268        if let Some(excerpt) = self.as_singleton() {
1269            return excerpt.buffer.clip_point_utf16(point, bias);
1270        }
1271
1272        let mut cursor = self.excerpts.cursor::<PointUtf16>();
1273        cursor.seek(&point, Bias::Right, &());
1274        let overshoot = if let Some(excerpt) = cursor.item() {
1275            let excerpt_start = excerpt
1276                .buffer
1277                .offset_to_point_utf16(excerpt.range.start.to_offset(&excerpt.buffer));
1278            let buffer_point = excerpt
1279                .buffer
1280                .clip_point_utf16(excerpt_start + (point - cursor.start()), bias);
1281            buffer_point.saturating_sub(excerpt_start)
1282        } else {
1283            PointUtf16::zero()
1284        };
1285        *cursor.start() + overshoot
1286    }
1287
1288    pub fn bytes_in_range<'a, T: ToOffset>(&'a self, range: Range<T>) -> MultiBufferBytes<'a> {
1289        let range = range.start.to_offset(self)..range.end.to_offset(self);
1290        let mut excerpts = self.excerpts.cursor::<usize>();
1291        excerpts.seek(&range.start, Bias::Right, &());
1292
1293        let mut chunk = &[][..];
1294        let excerpt_bytes = if let Some(excerpt) = excerpts.item() {
1295            let mut excerpt_bytes = excerpt
1296                .bytes_in_range(range.start - excerpts.start()..range.end - excerpts.start());
1297            chunk = excerpt_bytes.next().unwrap_or(&[][..]);
1298            Some(excerpt_bytes)
1299        } else {
1300            None
1301        };
1302
1303        MultiBufferBytes {
1304            range,
1305            excerpts,
1306            excerpt_bytes,
1307            chunk,
1308        }
1309    }
1310
1311    pub fn buffer_rows<'a>(&'a self, start_row: u32) -> MultiBufferRows<'a> {
1312        let mut result = MultiBufferRows {
1313            buffer_row_range: 0..0,
1314            excerpts: self.excerpts.cursor(),
1315        };
1316        result.seek(start_row);
1317        result
1318    }
1319
1320    pub fn chunks<'a, T: ToOffset>(
1321        &'a self,
1322        range: Range<T>,
1323        language_aware: bool,
1324    ) -> MultiBufferChunks<'a> {
1325        let range = range.start.to_offset(self)..range.end.to_offset(self);
1326        let mut chunks = MultiBufferChunks {
1327            range: range.clone(),
1328            excerpts: self.excerpts.cursor(),
1329            excerpt_chunks: None,
1330            language_aware,
1331        };
1332        chunks.seek(range.start);
1333        chunks
1334    }
1335
1336    pub fn offset_to_point(&self, offset: usize) -> Point {
1337        if let Some(excerpt) = self.as_singleton() {
1338            return excerpt.buffer.offset_to_point(offset);
1339        }
1340
1341        let mut cursor = self.excerpts.cursor::<(usize, Point)>();
1342        cursor.seek(&offset, Bias::Right, &());
1343        if let Some(excerpt) = cursor.item() {
1344            let (start_offset, start_point) = cursor.start();
1345            let overshoot = offset - start_offset;
1346            let excerpt_start_offset = excerpt.range.start.to_offset(&excerpt.buffer);
1347            let excerpt_start_point = excerpt.range.start.to_point(&excerpt.buffer);
1348            let buffer_point = excerpt
1349                .buffer
1350                .offset_to_point(excerpt_start_offset + overshoot);
1351            *start_point + (buffer_point - excerpt_start_point)
1352        } else {
1353            self.excerpts.summary().text.lines
1354        }
1355    }
1356
1357    pub fn offset_to_point_utf16(&self, offset: usize) -> PointUtf16 {
1358        if let Some(excerpt) = self.as_singleton() {
1359            return excerpt.buffer.offset_to_point_utf16(offset);
1360        }
1361
1362        let mut cursor = self.excerpts.cursor::<(usize, PointUtf16)>();
1363        cursor.seek(&offset, Bias::Right, &());
1364        if let Some(excerpt) = cursor.item() {
1365            let (start_offset, start_point) = cursor.start();
1366            let overshoot = offset - start_offset;
1367            let excerpt_start_offset = excerpt.range.start.to_offset(&excerpt.buffer);
1368            let excerpt_start_point = excerpt.range.start.to_point_utf16(&excerpt.buffer);
1369            let buffer_point = excerpt
1370                .buffer
1371                .offset_to_point_utf16(excerpt_start_offset + overshoot);
1372            *start_point + (buffer_point - excerpt_start_point)
1373        } else {
1374            self.excerpts.summary().text.lines_utf16
1375        }
1376    }
1377
1378    pub fn point_to_point_utf16(&self, point: Point) -> PointUtf16 {
1379        if let Some(excerpt) = self.as_singleton() {
1380            return excerpt.buffer.point_to_point_utf16(point);
1381        }
1382
1383        let mut cursor = self.excerpts.cursor::<(Point, PointUtf16)>();
1384        cursor.seek(&point, Bias::Right, &());
1385        if let Some(excerpt) = cursor.item() {
1386            let (start_offset, start_point) = cursor.start();
1387            let overshoot = point - start_offset;
1388            let excerpt_start_point = excerpt.range.start.to_point(&excerpt.buffer);
1389            let excerpt_start_point_utf16 = excerpt.range.start.to_point_utf16(&excerpt.buffer);
1390            let buffer_point = excerpt
1391                .buffer
1392                .point_to_point_utf16(excerpt_start_point + overshoot);
1393            *start_point + (buffer_point - excerpt_start_point_utf16)
1394        } else {
1395            self.excerpts.summary().text.lines_utf16
1396        }
1397    }
1398
1399    pub fn point_to_offset(&self, point: Point) -> usize {
1400        if let Some(excerpt) = self.as_singleton() {
1401            return excerpt.buffer.point_to_offset(point);
1402        }
1403
1404        let mut cursor = self.excerpts.cursor::<(Point, usize)>();
1405        cursor.seek(&point, Bias::Right, &());
1406        if let Some(excerpt) = cursor.item() {
1407            let (start_point, start_offset) = cursor.start();
1408            let overshoot = point - start_point;
1409            let excerpt_start_offset = excerpt.range.start.to_offset(&excerpt.buffer);
1410            let excerpt_start_point = excerpt.range.start.to_point(&excerpt.buffer);
1411            let buffer_offset = excerpt
1412                .buffer
1413                .point_to_offset(excerpt_start_point + overshoot);
1414            *start_offset + buffer_offset - excerpt_start_offset
1415        } else {
1416            self.excerpts.summary().text.bytes
1417        }
1418    }
1419
1420    pub fn point_utf16_to_offset(&self, point: PointUtf16) -> usize {
1421        if let Some(excerpt) = self.as_singleton() {
1422            return excerpt.buffer.point_utf16_to_offset(point);
1423        }
1424
1425        let mut cursor = self.excerpts.cursor::<(PointUtf16, usize)>();
1426        cursor.seek(&point, Bias::Right, &());
1427        if let Some(excerpt) = cursor.item() {
1428            let (start_point, start_offset) = cursor.start();
1429            let overshoot = point - start_point;
1430            let excerpt_start_offset = excerpt.range.start.to_offset(&excerpt.buffer);
1431            let excerpt_start_point = excerpt
1432                .buffer
1433                .offset_to_point_utf16(excerpt.range.start.to_offset(&excerpt.buffer));
1434            let buffer_offset = excerpt
1435                .buffer
1436                .point_utf16_to_offset(excerpt_start_point + overshoot);
1437            *start_offset + (buffer_offset - excerpt_start_offset)
1438        } else {
1439            self.excerpts.summary().text.bytes
1440        }
1441    }
1442
1443    pub fn indent_column_for_line(&self, row: u32) -> u32 {
1444        if let Some((buffer, range)) = self.buffer_line_for_row(row) {
1445            buffer
1446                .indent_column_for_line(range.start.row)
1447                .min(range.end.column)
1448                .saturating_sub(range.start.column)
1449        } else {
1450            0
1451        }
1452    }
1453
1454    pub fn line_len(&self, row: u32) -> u32 {
1455        if let Some((_, range)) = self.buffer_line_for_row(row) {
1456            range.end.column - range.start.column
1457        } else {
1458            0
1459        }
1460    }
1461
1462    fn buffer_line_for_row(&self, row: u32) -> Option<(&BufferSnapshot, Range<Point>)> {
1463        let mut cursor = self.excerpts.cursor::<Point>();
1464        cursor.seek(&Point::new(row, 0), Bias::Right, &());
1465        if let Some(excerpt) = cursor.item() {
1466            let overshoot = row - cursor.start().row;
1467            let excerpt_start = excerpt.range.start.to_point(&excerpt.buffer);
1468            let excerpt_end = excerpt.range.end.to_point(&excerpt.buffer);
1469            let buffer_row = excerpt_start.row + overshoot;
1470            let line_start = Point::new(buffer_row, 0);
1471            let line_end = Point::new(buffer_row, excerpt.buffer.line_len(buffer_row));
1472            return Some((
1473                &excerpt.buffer,
1474                line_start.max(excerpt_start)..line_end.min(excerpt_end),
1475            ));
1476        }
1477        None
1478    }
1479
1480    pub fn max_point(&self) -> Point {
1481        self.text_summary().lines
1482    }
1483
1484    pub fn text_summary(&self) -> TextSummary {
1485        self.excerpts.summary().text
1486    }
1487
1488    pub fn text_summary_for_range<'a, D, O>(&'a self, range: Range<O>) -> D
1489    where
1490        D: TextDimension,
1491        O: ToOffset,
1492    {
1493        let mut summary = D::default();
1494        let mut range = range.start.to_offset(self)..range.end.to_offset(self);
1495        let mut cursor = self.excerpts.cursor::<usize>();
1496        cursor.seek(&range.start, Bias::Right, &());
1497        if let Some(excerpt) = cursor.item() {
1498            let mut end_before_newline = cursor.end(&());
1499            if excerpt.has_trailing_newline {
1500                end_before_newline -= 1;
1501            }
1502
1503            let excerpt_start = excerpt.range.start.to_offset(&excerpt.buffer);
1504            let start_in_excerpt = excerpt_start + (range.start - cursor.start());
1505            let end_in_excerpt =
1506                excerpt_start + (cmp::min(end_before_newline, range.end) - cursor.start());
1507            summary.add_assign(
1508                &excerpt
1509                    .buffer
1510                    .text_summary_for_range(start_in_excerpt..end_in_excerpt),
1511            );
1512
1513            if range.end > end_before_newline {
1514                summary.add_assign(&D::from_text_summary(&TextSummary {
1515                    bytes: 1,
1516                    lines: Point::new(1 as u32, 0),
1517                    lines_utf16: PointUtf16::new(1 as u32, 0),
1518                    first_line_chars: 0,
1519                    last_line_chars: 0,
1520                    longest_row: 0,
1521                    longest_row_chars: 0,
1522                }));
1523            }
1524
1525            cursor.next(&());
1526        }
1527
1528        if range.end > *cursor.start() {
1529            summary.add_assign(&D::from_text_summary(&cursor.summary::<_, TextSummary>(
1530                &range.end,
1531                Bias::Right,
1532                &(),
1533            )));
1534            if let Some(excerpt) = cursor.item() {
1535                range.end = cmp::max(*cursor.start(), range.end);
1536
1537                let excerpt_start = excerpt.range.start.to_offset(&excerpt.buffer);
1538                let end_in_excerpt = excerpt_start + (range.end - cursor.start());
1539                summary.add_assign(
1540                    &excerpt
1541                        .buffer
1542                        .text_summary_for_range(excerpt_start..end_in_excerpt),
1543                );
1544            }
1545        }
1546
1547        summary
1548    }
1549
1550    pub fn summary_for_anchor<D>(&self, anchor: &Anchor) -> D
1551    where
1552        D: TextDimension + Ord + Sub<D, Output = D>,
1553    {
1554        let mut cursor = self.excerpts.cursor::<ExcerptSummary>();
1555        cursor.seek(&Some(&anchor.excerpt_id), Bias::Left, &());
1556        if cursor.item().is_none() {
1557            cursor.next(&());
1558        }
1559
1560        let mut position = D::from_text_summary(&cursor.start().text);
1561        if let Some(excerpt) = cursor.item() {
1562            if excerpt.id == anchor.excerpt_id && excerpt.buffer_id == anchor.buffer_id {
1563                let excerpt_buffer_start = excerpt.range.start.summary::<D>(&excerpt.buffer);
1564                let excerpt_buffer_end = excerpt.range.end.summary::<D>(&excerpt.buffer);
1565                let buffer_position = cmp::min(
1566                    excerpt_buffer_end,
1567                    anchor.text_anchor.summary::<D>(&excerpt.buffer),
1568                );
1569                if buffer_position > excerpt_buffer_start {
1570                    position.add_assign(&(buffer_position - excerpt_buffer_start));
1571                }
1572            }
1573        }
1574        position
1575    }
1576
1577    pub fn summaries_for_anchors<'a, D, I>(&'a self, anchors: I) -> Vec<D>
1578    where
1579        D: TextDimension + Ord + Sub<D, Output = D>,
1580        I: 'a + IntoIterator<Item = &'a Anchor>,
1581    {
1582        if let Some(excerpt) = self.as_singleton() {
1583            return excerpt
1584                .buffer
1585                .summaries_for_anchors(anchors.into_iter().map(|a| &a.text_anchor))
1586                .collect();
1587        }
1588
1589        let mut anchors = anchors.into_iter().peekable();
1590        let mut cursor = self.excerpts.cursor::<ExcerptSummary>();
1591        let mut summaries = Vec::new();
1592        while let Some(anchor) = anchors.peek() {
1593            let excerpt_id = &anchor.excerpt_id;
1594            let buffer_id = anchor.buffer_id;
1595            let excerpt_anchors = iter::from_fn(|| {
1596                let anchor = anchors.peek()?;
1597                if anchor.excerpt_id == *excerpt_id && anchor.buffer_id == buffer_id {
1598                    Some(&anchors.next().unwrap().text_anchor)
1599                } else {
1600                    None
1601                }
1602            });
1603
1604            cursor.seek_forward(&Some(excerpt_id), Bias::Left, &());
1605            if cursor.item().is_none() {
1606                cursor.next(&());
1607            }
1608
1609            let position = D::from_text_summary(&cursor.start().text);
1610            if let Some(excerpt) = cursor.item() {
1611                if excerpt.id == *excerpt_id && excerpt.buffer_id == buffer_id {
1612                    let excerpt_buffer_start = excerpt.range.start.summary::<D>(&excerpt.buffer);
1613                    let excerpt_buffer_end = excerpt.range.end.summary::<D>(&excerpt.buffer);
1614                    summaries.extend(
1615                        excerpt
1616                            .buffer
1617                            .summaries_for_anchors::<D, _>(excerpt_anchors)
1618                            .map(move |summary| {
1619                                let summary = cmp::min(excerpt_buffer_end.clone(), summary);
1620                                let mut position = position.clone();
1621                                let excerpt_buffer_start = excerpt_buffer_start.clone();
1622                                if summary > excerpt_buffer_start {
1623                                    position.add_assign(&(summary - excerpt_buffer_start));
1624                                }
1625                                position
1626                            }),
1627                    );
1628                    continue;
1629                }
1630            }
1631
1632            summaries.extend(excerpt_anchors.map(|_| position.clone()));
1633        }
1634
1635        summaries
1636    }
1637
1638    pub fn refresh_anchors<'a, I>(&'a self, anchors: I) -> Vec<(usize, Anchor, bool)>
1639    where
1640        I: 'a + IntoIterator<Item = &'a Anchor>,
1641    {
1642        let mut anchors = anchors.into_iter().enumerate().peekable();
1643        let mut cursor = self.excerpts.cursor::<Option<&ExcerptId>>();
1644        let mut result = Vec::new();
1645        while let Some((_, anchor)) = anchors.peek() {
1646            let old_excerpt_id = &anchor.excerpt_id;
1647
1648            // Find the location where this anchor's excerpt should be.
1649            cursor.seek_forward(&Some(old_excerpt_id), Bias::Left, &());
1650            if cursor.item().is_none() {
1651                cursor.next(&());
1652            }
1653
1654            let next_excerpt = cursor.item();
1655            let prev_excerpt = cursor.prev_item();
1656
1657            // Process all of the anchors for this excerpt.
1658            while let Some((_, anchor)) = anchors.peek() {
1659                if anchor.excerpt_id != *old_excerpt_id {
1660                    break;
1661                }
1662                let mut kept_position = false;
1663                let (anchor_ix, anchor) = anchors.next().unwrap();
1664                let mut anchor = anchor.clone();
1665
1666                // Leave min and max anchors unchanged.
1667                if *old_excerpt_id == ExcerptId::max() || *old_excerpt_id == ExcerptId::min() {
1668                    kept_position = true;
1669                }
1670                // If the old excerpt still exists at this location, then leave
1671                // the anchor unchanged.
1672                else if next_excerpt.map_or(false, |excerpt| {
1673                    excerpt.id == *old_excerpt_id && excerpt.contains(&anchor)
1674                }) {
1675                    kept_position = true;
1676                }
1677                // If the old excerpt no longer exists at this location, then attempt to
1678                // find an equivalent position for this anchor in an adjacent excerpt.
1679                else {
1680                    for excerpt in [next_excerpt, prev_excerpt].iter().filter_map(|e| *e) {
1681                        if excerpt.contains(&anchor) {
1682                            anchor.excerpt_id = excerpt.id.clone();
1683                            kept_position = true;
1684                            break;
1685                        }
1686                    }
1687                }
1688                // If there's no adjacent excerpt that contains the anchor's position,
1689                // then report that the anchor has lost its position.
1690                if !kept_position {
1691                    anchor = if let Some(excerpt) = next_excerpt {
1692                        let mut text_anchor = excerpt
1693                            .range
1694                            .start
1695                            .bias(anchor.text_anchor.bias, &excerpt.buffer);
1696                        if text_anchor
1697                            .cmp(&excerpt.range.end, &excerpt.buffer)
1698                            .unwrap()
1699                            .is_gt()
1700                        {
1701                            text_anchor = excerpt.range.end.clone();
1702                        }
1703                        Anchor {
1704                            buffer_id: excerpt.buffer_id,
1705                            excerpt_id: excerpt.id.clone(),
1706                            text_anchor,
1707                        }
1708                    } else if let Some(excerpt) = prev_excerpt {
1709                        let mut text_anchor = excerpt
1710                            .range
1711                            .end
1712                            .bias(anchor.text_anchor.bias, &excerpt.buffer);
1713                        if text_anchor
1714                            .cmp(&excerpt.range.start, &excerpt.buffer)
1715                            .unwrap()
1716                            .is_lt()
1717                        {
1718                            text_anchor = excerpt.range.start.clone();
1719                        }
1720                        Anchor {
1721                            buffer_id: excerpt.buffer_id,
1722                            excerpt_id: excerpt.id.clone(),
1723                            text_anchor,
1724                        }
1725                    } else if anchor.text_anchor.bias == Bias::Left {
1726                        Anchor::min()
1727                    } else {
1728                        Anchor::max()
1729                    };
1730                }
1731
1732                result.push((anchor_ix, anchor, kept_position));
1733            }
1734        }
1735        result.sort_unstable_by(|a, b| a.1.cmp(&b.1, self).unwrap());
1736        result
1737    }
1738
1739    pub fn anchor_before<T: ToOffset>(&self, position: T) -> Anchor {
1740        self.anchor_at(position, Bias::Left)
1741    }
1742
1743    pub fn anchor_after<T: ToOffset>(&self, position: T) -> Anchor {
1744        self.anchor_at(position, Bias::Right)
1745    }
1746
1747    pub fn anchor_at<T: ToOffset>(&self, position: T, mut bias: Bias) -> Anchor {
1748        let offset = position.to_offset(self);
1749        if let Some(excerpt) = self.as_singleton() {
1750            return Anchor {
1751                buffer_id: excerpt.buffer_id,
1752                excerpt_id: excerpt.id.clone(),
1753                text_anchor: excerpt.buffer.anchor_at(offset, bias),
1754            };
1755        }
1756
1757        let mut cursor = self.excerpts.cursor::<(usize, Option<&ExcerptId>)>();
1758        cursor.seek(&offset, Bias::Right, &());
1759        if cursor.item().is_none() && offset == cursor.start().0 && bias == Bias::Left {
1760            cursor.prev(&());
1761        }
1762        if let Some(excerpt) = cursor.item() {
1763            let mut overshoot = offset.saturating_sub(cursor.start().0);
1764            if excerpt.has_trailing_newline && offset == cursor.end(&()).0 {
1765                overshoot -= 1;
1766                bias = Bias::Right;
1767            }
1768
1769            let buffer_start = excerpt.range.start.to_offset(&excerpt.buffer);
1770            let text_anchor =
1771                excerpt.clip_anchor(excerpt.buffer.anchor_at(buffer_start + overshoot, bias));
1772            Anchor {
1773                buffer_id: excerpt.buffer_id,
1774                excerpt_id: excerpt.id.clone(),
1775                text_anchor,
1776            }
1777        } else if offset == 0 && bias == Bias::Left {
1778            Anchor::min()
1779        } else {
1780            Anchor::max()
1781        }
1782    }
1783
1784    pub fn anchor_in_excerpt(&self, excerpt_id: ExcerptId, text_anchor: text::Anchor) -> Anchor {
1785        let mut cursor = self.excerpts.cursor::<Option<&ExcerptId>>();
1786        cursor.seek(&Some(&excerpt_id), Bias::Left, &());
1787        if let Some(excerpt) = cursor.item() {
1788            if excerpt.id == excerpt_id {
1789                let text_anchor = excerpt.clip_anchor(text_anchor);
1790                drop(cursor);
1791                return Anchor {
1792                    buffer_id: excerpt.buffer_id,
1793                    excerpt_id,
1794                    text_anchor,
1795                };
1796            }
1797        }
1798        panic!("excerpt not found");
1799    }
1800
1801    pub fn can_resolve(&self, anchor: &Anchor) -> bool {
1802        if anchor.excerpt_id == ExcerptId::min() || anchor.excerpt_id == ExcerptId::max() {
1803            true
1804        } else if let Some((buffer_id, buffer_snapshot)) =
1805            self.buffer_snapshot_for_excerpt(&anchor.excerpt_id)
1806        {
1807            anchor.buffer_id == buffer_id && buffer_snapshot.can_resolve(&anchor.text_anchor)
1808        } else {
1809            false
1810        }
1811    }
1812
1813    pub fn excerpt_boundaries_in_range<'a, R, T>(
1814        &'a self,
1815        range: R,
1816    ) -> impl Iterator<Item = ExcerptBoundary> + 'a
1817    where
1818        R: RangeBounds<T>,
1819        T: ToOffset,
1820    {
1821        let start_offset;
1822        let start = match range.start_bound() {
1823            Bound::Included(start) => {
1824                start_offset = start.to_offset(self);
1825                Bound::Included(start_offset)
1826            }
1827            Bound::Excluded(start) => {
1828                start_offset = start.to_offset(self);
1829                Bound::Excluded(start_offset)
1830            }
1831            Bound::Unbounded => {
1832                start_offset = 0;
1833                Bound::Unbounded
1834            }
1835        };
1836        let end = match range.end_bound() {
1837            Bound::Included(end) => Bound::Included(end.to_offset(self)),
1838            Bound::Excluded(end) => Bound::Excluded(end.to_offset(self)),
1839            Bound::Unbounded => Bound::Unbounded,
1840        };
1841        let bounds = (start, end);
1842
1843        let mut cursor = self.excerpts.cursor::<(usize, Point)>();
1844        cursor.seek(&start_offset, Bias::Right, &());
1845        if cursor.item().is_none() {
1846            cursor.prev(&());
1847        }
1848        if !bounds.contains(&cursor.start().0) {
1849            cursor.next(&());
1850        }
1851
1852        let mut prev_buffer_id = cursor.prev_item().map(|excerpt| excerpt.buffer_id);
1853        std::iter::from_fn(move || {
1854            if self.singleton {
1855                None
1856            } else if bounds.contains(&cursor.start().0) {
1857                let excerpt = cursor.item()?;
1858                let starts_new_buffer = Some(excerpt.buffer_id) != prev_buffer_id;
1859                let boundary = ExcerptBoundary {
1860                    row: cursor.start().1.row,
1861                    buffer: excerpt.buffer.clone(),
1862                    range: excerpt.range.clone(),
1863                    starts_new_buffer,
1864                };
1865
1866                prev_buffer_id = Some(excerpt.buffer_id);
1867                cursor.next(&());
1868                Some(boundary)
1869            } else {
1870                None
1871            }
1872        })
1873    }
1874
1875    pub fn parse_count(&self) -> usize {
1876        self.parse_count
1877    }
1878
1879    pub fn enclosing_bracket_ranges<T: ToOffset>(
1880        &self,
1881        range: Range<T>,
1882    ) -> Option<(Range<usize>, Range<usize>)> {
1883        let range = range.start.to_offset(self)..range.end.to_offset(self);
1884
1885        let mut cursor = self.excerpts.cursor::<usize>();
1886        cursor.seek(&range.start, Bias::Right, &());
1887        let start_excerpt = cursor.item();
1888
1889        cursor.seek(&range.end, Bias::Right, &());
1890        let end_excerpt = cursor.item();
1891
1892        start_excerpt
1893            .zip(end_excerpt)
1894            .and_then(|(start_excerpt, end_excerpt)| {
1895                if start_excerpt.id != end_excerpt.id {
1896                    return None;
1897                }
1898
1899                let excerpt_buffer_start =
1900                    start_excerpt.range.start.to_offset(&start_excerpt.buffer);
1901                let excerpt_buffer_end = excerpt_buffer_start + start_excerpt.text_summary.bytes;
1902
1903                let start_in_buffer =
1904                    excerpt_buffer_start + range.start.saturating_sub(*cursor.start());
1905                let end_in_buffer =
1906                    excerpt_buffer_start + range.end.saturating_sub(*cursor.start());
1907                let (mut start_bracket_range, mut end_bracket_range) = start_excerpt
1908                    .buffer
1909                    .enclosing_bracket_ranges(start_in_buffer..end_in_buffer)?;
1910
1911                if start_bracket_range.start >= excerpt_buffer_start
1912                    && end_bracket_range.end < excerpt_buffer_end
1913                {
1914                    start_bracket_range.start =
1915                        cursor.start() + (start_bracket_range.start - excerpt_buffer_start);
1916                    start_bracket_range.end =
1917                        cursor.start() + (start_bracket_range.end - excerpt_buffer_start);
1918                    end_bracket_range.start =
1919                        cursor.start() + (end_bracket_range.start - excerpt_buffer_start);
1920                    end_bracket_range.end =
1921                        cursor.start() + (end_bracket_range.end - excerpt_buffer_start);
1922                    Some((start_bracket_range, end_bracket_range))
1923                } else {
1924                    None
1925                }
1926            })
1927    }
1928
1929    pub fn diagnostics_update_count(&self) -> usize {
1930        self.diagnostics_update_count
1931    }
1932
1933    pub fn trailing_excerpt_update_count(&self) -> usize {
1934        self.trailing_excerpt_update_count
1935    }
1936
1937    pub fn language(&self) -> Option<&Arc<Language>> {
1938        self.excerpts
1939            .iter()
1940            .next()
1941            .and_then(|excerpt| excerpt.buffer.language())
1942    }
1943
1944    pub fn is_dirty(&self) -> bool {
1945        self.is_dirty
1946    }
1947
1948    pub fn has_conflict(&self) -> bool {
1949        self.has_conflict
1950    }
1951
1952    pub fn diagnostic_group<'a, O>(
1953        &'a self,
1954        group_id: usize,
1955    ) -> impl Iterator<Item = DiagnosticEntry<O>> + 'a
1956    where
1957        O: text::FromAnchor + 'a,
1958    {
1959        self.as_singleton()
1960            .into_iter()
1961            .flat_map(move |excerpt| excerpt.buffer.diagnostic_group(group_id))
1962    }
1963
1964    pub fn diagnostics_in_range<'a, T, O>(
1965        &'a self,
1966        range: Range<T>,
1967    ) -> impl Iterator<Item = DiagnosticEntry<O>> + 'a
1968    where
1969        T: 'a + ToOffset,
1970        O: 'a + text::FromAnchor,
1971    {
1972        self.as_singleton().into_iter().flat_map(move |excerpt| {
1973            excerpt
1974                .buffer
1975                .diagnostics_in_range(range.start.to_offset(self)..range.end.to_offset(self))
1976        })
1977    }
1978
1979    pub fn range_for_syntax_ancestor<T: ToOffset>(&self, range: Range<T>) -> Option<Range<usize>> {
1980        let range = range.start.to_offset(self)..range.end.to_offset(self);
1981
1982        let mut cursor = self.excerpts.cursor::<usize>();
1983        cursor.seek(&range.start, Bias::Right, &());
1984        let start_excerpt = cursor.item();
1985
1986        cursor.seek(&range.end, Bias::Right, &());
1987        let end_excerpt = cursor.item();
1988
1989        start_excerpt
1990            .zip(end_excerpt)
1991            .and_then(|(start_excerpt, end_excerpt)| {
1992                if start_excerpt.id != end_excerpt.id {
1993                    return None;
1994                }
1995
1996                let excerpt_buffer_start =
1997                    start_excerpt.range.start.to_offset(&start_excerpt.buffer);
1998                let excerpt_buffer_end = excerpt_buffer_start + start_excerpt.text_summary.bytes;
1999
2000                let start_in_buffer =
2001                    excerpt_buffer_start + range.start.saturating_sub(*cursor.start());
2002                let end_in_buffer =
2003                    excerpt_buffer_start + range.end.saturating_sub(*cursor.start());
2004                let mut ancestor_buffer_range = start_excerpt
2005                    .buffer
2006                    .range_for_syntax_ancestor(start_in_buffer..end_in_buffer)?;
2007                ancestor_buffer_range.start =
2008                    cmp::max(ancestor_buffer_range.start, excerpt_buffer_start);
2009                ancestor_buffer_range.end = cmp::min(ancestor_buffer_range.end, excerpt_buffer_end);
2010
2011                let start = cursor.start() + (ancestor_buffer_range.start - excerpt_buffer_start);
2012                let end = cursor.start() + (ancestor_buffer_range.end - excerpt_buffer_start);
2013                Some(start..end)
2014            })
2015    }
2016
2017    pub fn outline(&self, theme: Option<&SyntaxTheme>) -> Option<Outline<Anchor>> {
2018        let excerpt = self.as_singleton()?;
2019        let outline = excerpt.buffer.outline(theme)?;
2020        Some(Outline::new(
2021            outline
2022                .items
2023                .into_iter()
2024                .map(|item| OutlineItem {
2025                    depth: item.depth,
2026                    range: self.anchor_in_excerpt(excerpt.id.clone(), item.range.start)
2027                        ..self.anchor_in_excerpt(excerpt.id.clone(), item.range.end),
2028                    text: item.text,
2029                    highlight_ranges: item.highlight_ranges,
2030                    name_ranges: item.name_ranges,
2031                })
2032                .collect(),
2033        ))
2034    }
2035
2036    fn buffer_snapshot_for_excerpt<'a>(
2037        &'a self,
2038        excerpt_id: &'a ExcerptId,
2039    ) -> Option<(usize, &'a BufferSnapshot)> {
2040        let mut cursor = self.excerpts.cursor::<Option<&ExcerptId>>();
2041        cursor.seek(&Some(excerpt_id), Bias::Left, &());
2042        if let Some(excerpt) = cursor.item() {
2043            if excerpt.id == *excerpt_id {
2044                return Some((excerpt.buffer_id, &excerpt.buffer));
2045            }
2046        }
2047        None
2048    }
2049
2050    pub fn remote_selections_in_range<'a>(
2051        &'a self,
2052        range: &'a Range<Anchor>,
2053    ) -> impl 'a + Iterator<Item = (ReplicaId, Selection<Anchor>)> {
2054        let mut cursor = self.excerpts.cursor::<Option<&ExcerptId>>();
2055        cursor.seek(&Some(&range.start.excerpt_id), Bias::Left, &());
2056        cursor
2057            .take_while(move |excerpt| excerpt.id <= range.end.excerpt_id)
2058            .flat_map(move |excerpt| {
2059                let mut query_range = excerpt.range.start.clone()..excerpt.range.end.clone();
2060                if excerpt.id == range.start.excerpt_id {
2061                    query_range.start = range.start.text_anchor.clone();
2062                }
2063                if excerpt.id == range.end.excerpt_id {
2064                    query_range.end = range.end.text_anchor.clone();
2065                }
2066
2067                excerpt
2068                    .buffer
2069                    .remote_selections_in_range(query_range)
2070                    .flat_map(move |(replica_id, selections)| {
2071                        selections.map(move |selection| {
2072                            let mut start = Anchor {
2073                                buffer_id: excerpt.buffer_id,
2074                                excerpt_id: excerpt.id.clone(),
2075                                text_anchor: selection.start.clone(),
2076                            };
2077                            let mut end = Anchor {
2078                                buffer_id: excerpt.buffer_id,
2079                                excerpt_id: excerpt.id.clone(),
2080                                text_anchor: selection.end.clone(),
2081                            };
2082                            if range.start.cmp(&start, self).unwrap().is_gt() {
2083                                start = range.start.clone();
2084                            }
2085                            if range.end.cmp(&end, self).unwrap().is_lt() {
2086                                end = range.end.clone();
2087                            }
2088
2089                            (
2090                                replica_id,
2091                                Selection {
2092                                    id: selection.id,
2093                                    start,
2094                                    end,
2095                                    reversed: selection.reversed,
2096                                    goal: selection.goal,
2097                                },
2098                            )
2099                        })
2100                    })
2101            })
2102    }
2103}
2104
2105impl History {
2106    fn start_transaction(&mut self, now: Instant) -> Option<TransactionId> {
2107        self.transaction_depth += 1;
2108        if self.transaction_depth == 1 {
2109            let id = self.next_transaction_id.tick();
2110            self.undo_stack.push(Transaction {
2111                id,
2112                buffer_transactions: Default::default(),
2113                first_edit_at: now,
2114                last_edit_at: now,
2115            });
2116            Some(id)
2117        } else {
2118            None
2119        }
2120    }
2121
2122    fn end_transaction(
2123        &mut self,
2124        now: Instant,
2125        buffer_transactions: HashSet<(usize, TransactionId)>,
2126    ) -> bool {
2127        assert_ne!(self.transaction_depth, 0);
2128        self.transaction_depth -= 1;
2129        if self.transaction_depth == 0 {
2130            if buffer_transactions.is_empty() {
2131                self.undo_stack.pop();
2132                false
2133            } else {
2134                let transaction = self.undo_stack.last_mut().unwrap();
2135                transaction.last_edit_at = now;
2136                transaction.buffer_transactions.extend(buffer_transactions);
2137                true
2138            }
2139        } else {
2140            false
2141        }
2142    }
2143
2144    fn pop_undo(&mut self) -> Option<&Transaction> {
2145        assert_eq!(self.transaction_depth, 0);
2146        if let Some(transaction) = self.undo_stack.pop() {
2147            self.redo_stack.push(transaction);
2148            self.redo_stack.last()
2149        } else {
2150            None
2151        }
2152    }
2153
2154    fn pop_redo(&mut self) -> Option<&Transaction> {
2155        assert_eq!(self.transaction_depth, 0);
2156        if let Some(transaction) = self.redo_stack.pop() {
2157            self.undo_stack.push(transaction);
2158            self.undo_stack.last()
2159        } else {
2160            None
2161        }
2162    }
2163
2164    fn group(&mut self) -> Option<TransactionId> {
2165        let mut new_len = self.undo_stack.len();
2166        let mut transactions = self.undo_stack.iter_mut();
2167
2168        if let Some(mut transaction) = transactions.next_back() {
2169            while let Some(prev_transaction) = transactions.next_back() {
2170                if transaction.first_edit_at - prev_transaction.last_edit_at <= self.group_interval
2171                {
2172                    transaction = prev_transaction;
2173                    new_len -= 1;
2174                } else {
2175                    break;
2176                }
2177            }
2178        }
2179
2180        let (transactions_to_keep, transactions_to_merge) = self.undo_stack.split_at_mut(new_len);
2181        if let Some(last_transaction) = transactions_to_keep.last_mut() {
2182            if let Some(transaction) = transactions_to_merge.last() {
2183                last_transaction.last_edit_at = transaction.last_edit_at;
2184            }
2185        }
2186
2187        self.undo_stack.truncate(new_len);
2188        self.undo_stack.last().map(|t| t.id)
2189    }
2190}
2191
2192impl Excerpt {
2193    fn new(
2194        id: ExcerptId,
2195        buffer_id: usize,
2196        buffer: BufferSnapshot,
2197        range: Range<text::Anchor>,
2198        has_trailing_newline: bool,
2199    ) -> Self {
2200        Excerpt {
2201            id,
2202            max_buffer_row: range.end.to_point(&buffer).row,
2203            text_summary: buffer.text_summary_for_range::<TextSummary, _>(range.to_offset(&buffer)),
2204            buffer_id,
2205            buffer,
2206            range,
2207            has_trailing_newline,
2208        }
2209    }
2210
2211    fn chunks_in_range<'a>(
2212        &'a self,
2213        range: Range<usize>,
2214        language_aware: bool,
2215    ) -> ExcerptChunks<'a> {
2216        let content_start = self.range.start.to_offset(&self.buffer);
2217        let chunks_start = content_start + range.start;
2218        let chunks_end = content_start + cmp::min(range.end, self.text_summary.bytes);
2219
2220        let footer_height = if self.has_trailing_newline
2221            && range.start <= self.text_summary.bytes
2222            && range.end > self.text_summary.bytes
2223        {
2224            1
2225        } else {
2226            0
2227        };
2228
2229        let content_chunks = self.buffer.chunks(chunks_start..chunks_end, language_aware);
2230
2231        ExcerptChunks {
2232            content_chunks,
2233            footer_height,
2234        }
2235    }
2236
2237    fn bytes_in_range(&self, range: Range<usize>) -> ExcerptBytes {
2238        let content_start = self.range.start.to_offset(&self.buffer);
2239        let bytes_start = content_start + range.start;
2240        let bytes_end = content_start + cmp::min(range.end, self.text_summary.bytes);
2241        let footer_height = if self.has_trailing_newline
2242            && range.start <= self.text_summary.bytes
2243            && range.end > self.text_summary.bytes
2244        {
2245            1
2246        } else {
2247            0
2248        };
2249        let content_bytes = self.buffer.bytes_in_range(bytes_start..bytes_end);
2250
2251        ExcerptBytes {
2252            content_bytes,
2253            footer_height,
2254        }
2255    }
2256
2257    fn clip_anchor(&self, text_anchor: text::Anchor) -> text::Anchor {
2258        if text_anchor
2259            .cmp(&self.range.start, &self.buffer)
2260            .unwrap()
2261            .is_lt()
2262        {
2263            self.range.start.clone()
2264        } else if text_anchor
2265            .cmp(&self.range.end, &self.buffer)
2266            .unwrap()
2267            .is_gt()
2268        {
2269            self.range.end.clone()
2270        } else {
2271            text_anchor
2272        }
2273    }
2274
2275    fn contains(&self, anchor: &Anchor) -> bool {
2276        self.buffer_id == anchor.buffer_id
2277            && self
2278                .range
2279                .start
2280                .cmp(&anchor.text_anchor, &self.buffer)
2281                .unwrap()
2282                .is_le()
2283            && self
2284                .range
2285                .end
2286                .cmp(&anchor.text_anchor, &self.buffer)
2287                .unwrap()
2288                .is_ge()
2289    }
2290}
2291
2292impl fmt::Debug for Excerpt {
2293    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2294        f.debug_struct("Excerpt")
2295            .field("id", &self.id)
2296            .field("buffer_id", &self.buffer_id)
2297            .field("range", &self.range)
2298            .field("text_summary", &self.text_summary)
2299            .field("has_trailing_newline", &self.has_trailing_newline)
2300            .finish()
2301    }
2302}
2303
2304impl sum_tree::Item for Excerpt {
2305    type Summary = ExcerptSummary;
2306
2307    fn summary(&self) -> Self::Summary {
2308        let mut text = self.text_summary.clone();
2309        if self.has_trailing_newline {
2310            text += TextSummary::from("\n");
2311        }
2312        ExcerptSummary {
2313            excerpt_id: self.id.clone(),
2314            max_buffer_row: self.max_buffer_row,
2315            text,
2316        }
2317    }
2318}
2319
2320impl sum_tree::Summary for ExcerptSummary {
2321    type Context = ();
2322
2323    fn add_summary(&mut self, summary: &Self, _: &()) {
2324        debug_assert!(summary.excerpt_id > self.excerpt_id);
2325        self.excerpt_id = summary.excerpt_id.clone();
2326        self.text.add_summary(&summary.text, &());
2327        self.max_buffer_row = cmp::max(self.max_buffer_row, summary.max_buffer_row);
2328    }
2329}
2330
2331impl<'a> sum_tree::Dimension<'a, ExcerptSummary> for TextSummary {
2332    fn add_summary(&mut self, summary: &'a ExcerptSummary, _: &()) {
2333        *self += &summary.text;
2334    }
2335}
2336
2337impl<'a> sum_tree::Dimension<'a, ExcerptSummary> for usize {
2338    fn add_summary(&mut self, summary: &'a ExcerptSummary, _: &()) {
2339        *self += summary.text.bytes;
2340    }
2341}
2342
2343impl<'a> sum_tree::SeekTarget<'a, ExcerptSummary, ExcerptSummary> for usize {
2344    fn cmp(&self, cursor_location: &ExcerptSummary, _: &()) -> cmp::Ordering {
2345        Ord::cmp(self, &cursor_location.text.bytes)
2346    }
2347}
2348
2349impl<'a> sum_tree::SeekTarget<'a, ExcerptSummary, ExcerptSummary> for Option<&'a ExcerptId> {
2350    fn cmp(&self, cursor_location: &ExcerptSummary, _: &()) -> cmp::Ordering {
2351        Ord::cmp(self, &Some(&cursor_location.excerpt_id))
2352    }
2353}
2354
2355impl<'a> sum_tree::Dimension<'a, ExcerptSummary> for Point {
2356    fn add_summary(&mut self, summary: &'a ExcerptSummary, _: &()) {
2357        *self += summary.text.lines;
2358    }
2359}
2360
2361impl<'a> sum_tree::Dimension<'a, ExcerptSummary> for PointUtf16 {
2362    fn add_summary(&mut self, summary: &'a ExcerptSummary, _: &()) {
2363        *self += summary.text.lines_utf16
2364    }
2365}
2366
2367impl<'a> sum_tree::Dimension<'a, ExcerptSummary> for Option<&'a ExcerptId> {
2368    fn add_summary(&mut self, summary: &'a ExcerptSummary, _: &()) {
2369        *self = Some(&summary.excerpt_id);
2370    }
2371}
2372
2373impl<'a> MultiBufferRows<'a> {
2374    pub fn seek(&mut self, row: u32) {
2375        self.buffer_row_range = 0..0;
2376
2377        self.excerpts
2378            .seek_forward(&Point::new(row, 0), Bias::Right, &());
2379        if self.excerpts.item().is_none() {
2380            self.excerpts.prev(&());
2381
2382            if self.excerpts.item().is_none() && row == 0 {
2383                self.buffer_row_range = 0..1;
2384                return;
2385            }
2386        }
2387
2388        if let Some(excerpt) = self.excerpts.item() {
2389            let overshoot = row - self.excerpts.start().row;
2390            let excerpt_start = excerpt.range.start.to_point(&excerpt.buffer).row;
2391            self.buffer_row_range.start = excerpt_start + overshoot;
2392            self.buffer_row_range.end = excerpt_start + excerpt.text_summary.lines.row + 1;
2393        }
2394    }
2395}
2396
2397impl<'a> Iterator for MultiBufferRows<'a> {
2398    type Item = Option<u32>;
2399
2400    fn next(&mut self) -> Option<Self::Item> {
2401        loop {
2402            if !self.buffer_row_range.is_empty() {
2403                let row = Some(self.buffer_row_range.start);
2404                self.buffer_row_range.start += 1;
2405                return Some(row);
2406            }
2407            self.excerpts.item()?;
2408            self.excerpts.next(&());
2409            let excerpt = self.excerpts.item()?;
2410            self.buffer_row_range.start = excerpt.range.start.to_point(&excerpt.buffer).row;
2411            self.buffer_row_range.end =
2412                self.buffer_row_range.start + excerpt.text_summary.lines.row + 1;
2413        }
2414    }
2415}
2416
2417impl<'a> MultiBufferChunks<'a> {
2418    pub fn offset(&self) -> usize {
2419        self.range.start
2420    }
2421
2422    pub fn seek(&mut self, offset: usize) {
2423        self.range.start = offset;
2424        self.excerpts.seek(&offset, Bias::Right, &());
2425        if let Some(excerpt) = self.excerpts.item() {
2426            self.excerpt_chunks = Some(excerpt.chunks_in_range(
2427                self.range.start - self.excerpts.start()..self.range.end - self.excerpts.start(),
2428                self.language_aware,
2429            ));
2430        } else {
2431            self.excerpt_chunks = None;
2432        }
2433    }
2434}
2435
2436impl<'a> Iterator for MultiBufferChunks<'a> {
2437    type Item = Chunk<'a>;
2438
2439    fn next(&mut self) -> Option<Self::Item> {
2440        if self.range.is_empty() {
2441            None
2442        } else if let Some(chunk) = self.excerpt_chunks.as_mut()?.next() {
2443            self.range.start += chunk.text.len();
2444            Some(chunk)
2445        } else {
2446            self.excerpts.next(&());
2447            let excerpt = self.excerpts.item()?;
2448            self.excerpt_chunks = Some(excerpt.chunks_in_range(
2449                0..self.range.end - self.excerpts.start(),
2450                self.language_aware,
2451            ));
2452            self.next()
2453        }
2454    }
2455}
2456
2457impl<'a> MultiBufferBytes<'a> {
2458    fn consume(&mut self, len: usize) {
2459        self.range.start += len;
2460        self.chunk = &self.chunk[len..];
2461
2462        if !self.range.is_empty() && self.chunk.is_empty() {
2463            if let Some(chunk) = self.excerpt_bytes.as_mut().and_then(|bytes| bytes.next()) {
2464                self.chunk = chunk;
2465            } else {
2466                self.excerpts.next(&());
2467                if let Some(excerpt) = self.excerpts.item() {
2468                    let mut excerpt_bytes =
2469                        excerpt.bytes_in_range(0..self.range.end - self.excerpts.start());
2470                    self.chunk = excerpt_bytes.next().unwrap();
2471                    self.excerpt_bytes = Some(excerpt_bytes);
2472                }
2473            }
2474        }
2475    }
2476}
2477
2478impl<'a> Iterator for MultiBufferBytes<'a> {
2479    type Item = &'a [u8];
2480
2481    fn next(&mut self) -> Option<Self::Item> {
2482        let chunk = self.chunk;
2483        if chunk.is_empty() {
2484            None
2485        } else {
2486            self.consume(chunk.len());
2487            Some(chunk)
2488        }
2489    }
2490}
2491
2492impl<'a> io::Read for MultiBufferBytes<'a> {
2493    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
2494        let len = cmp::min(buf.len(), self.chunk.len());
2495        buf[..len].copy_from_slice(&self.chunk[..len]);
2496        if len > 0 {
2497            self.consume(len);
2498        }
2499        Ok(len)
2500    }
2501}
2502
2503impl<'a> Iterator for ExcerptBytes<'a> {
2504    type Item = &'a [u8];
2505
2506    fn next(&mut self) -> Option<Self::Item> {
2507        if let Some(chunk) = self.content_bytes.next() {
2508            if !chunk.is_empty() {
2509                return Some(chunk);
2510            }
2511        }
2512
2513        if self.footer_height > 0 {
2514            let result = &NEWLINES[..self.footer_height];
2515            self.footer_height = 0;
2516            return Some(result);
2517        }
2518
2519        None
2520    }
2521}
2522
2523impl<'a> Iterator for ExcerptChunks<'a> {
2524    type Item = Chunk<'a>;
2525
2526    fn next(&mut self) -> Option<Self::Item> {
2527        if let Some(chunk) = self.content_chunks.next() {
2528            return Some(chunk);
2529        }
2530
2531        if self.footer_height > 0 {
2532            let text = unsafe { str::from_utf8_unchecked(&NEWLINES[..self.footer_height]) };
2533            self.footer_height = 0;
2534            return Some(Chunk {
2535                text,
2536                ..Default::default()
2537            });
2538        }
2539
2540        None
2541    }
2542}
2543
2544impl ToOffset for Point {
2545    fn to_offset<'a>(&self, snapshot: &MultiBufferSnapshot) -> usize {
2546        snapshot.point_to_offset(*self)
2547    }
2548}
2549
2550impl ToOffset for PointUtf16 {
2551    fn to_offset<'a>(&self, snapshot: &MultiBufferSnapshot) -> usize {
2552        snapshot.point_utf16_to_offset(*self)
2553    }
2554}
2555
2556impl ToOffset for usize {
2557    fn to_offset<'a>(&self, snapshot: &MultiBufferSnapshot) -> usize {
2558        assert!(*self <= snapshot.len(), "offset is out of range");
2559        *self
2560    }
2561}
2562
2563impl ToPoint for usize {
2564    fn to_point<'a>(&self, snapshot: &MultiBufferSnapshot) -> Point {
2565        snapshot.offset_to_point(*self)
2566    }
2567}
2568
2569impl ToPoint for Point {
2570    fn to_point<'a>(&self, _: &MultiBufferSnapshot) -> Point {
2571        *self
2572    }
2573}
2574
2575impl ToPointUtf16 for usize {
2576    fn to_point_utf16<'a>(&self, snapshot: &MultiBufferSnapshot) -> PointUtf16 {
2577        snapshot.offset_to_point_utf16(*self)
2578    }
2579}
2580
2581impl ToPointUtf16 for Point {
2582    fn to_point_utf16<'a>(&self, snapshot: &MultiBufferSnapshot) -> PointUtf16 {
2583        snapshot.point_to_point_utf16(*self)
2584    }
2585}
2586
2587impl ToPointUtf16 for PointUtf16 {
2588    fn to_point_utf16<'a>(&self, _: &MultiBufferSnapshot) -> PointUtf16 {
2589        *self
2590    }
2591}
2592
2593pub fn char_kind(c: char) -> CharKind {
2594    if c == '\n' {
2595        CharKind::Newline
2596    } else if c.is_whitespace() {
2597        CharKind::Whitespace
2598    } else if c.is_alphanumeric() || c == '_' {
2599        CharKind::Word
2600    } else {
2601        CharKind::Punctuation
2602    }
2603}
2604
2605#[cfg(test)]
2606mod tests {
2607    use super::*;
2608    use gpui::MutableAppContext;
2609    use language::{Buffer, Rope};
2610    use rand::prelude::*;
2611    use std::env;
2612    use text::{Point, RandomCharIter};
2613    use util::test::sample_text;
2614
2615    #[gpui::test]
2616    fn test_singleton_multibuffer(cx: &mut MutableAppContext) {
2617        let buffer = cx.add_model(|cx| Buffer::new(0, sample_text(6, 6, 'a'), cx));
2618        let multibuffer = cx.add_model(|cx| MultiBuffer::singleton(buffer.clone(), cx));
2619
2620        let snapshot = multibuffer.read(cx).snapshot(cx);
2621        assert_eq!(snapshot.text(), buffer.read(cx).text());
2622
2623        assert_eq!(
2624            snapshot.buffer_rows(0).collect::<Vec<_>>(),
2625            (0..buffer.read(cx).row_count())
2626                .map(Some)
2627                .collect::<Vec<_>>()
2628        );
2629
2630        buffer.update(cx, |buffer, cx| buffer.edit([1..3], "XXX\n", cx));
2631        let snapshot = multibuffer.read(cx).snapshot(cx);
2632
2633        assert_eq!(snapshot.text(), buffer.read(cx).text());
2634        assert_eq!(
2635            snapshot.buffer_rows(0).collect::<Vec<_>>(),
2636            (0..buffer.read(cx).row_count())
2637                .map(Some)
2638                .collect::<Vec<_>>()
2639        );
2640    }
2641
2642    #[gpui::test]
2643    fn test_remote_multibuffer(cx: &mut MutableAppContext) {
2644        let host_buffer = cx.add_model(|cx| Buffer::new(0, "a", cx));
2645        let guest_buffer = cx.add_model(|cx| {
2646            let message = host_buffer.read(cx).to_proto();
2647            Buffer::from_proto(1, message, None, cx).unwrap()
2648        });
2649        let multibuffer = cx.add_model(|cx| MultiBuffer::singleton(guest_buffer.clone(), cx));
2650        let snapshot = multibuffer.read(cx).snapshot(cx);
2651        assert_eq!(snapshot.text(), "a");
2652
2653        guest_buffer.update(cx, |buffer, cx| buffer.edit([1..1], "b", cx));
2654        let snapshot = multibuffer.read(cx).snapshot(cx);
2655        assert_eq!(snapshot.text(), "ab");
2656
2657        guest_buffer.update(cx, |buffer, cx| buffer.edit([2..2], "c", cx));
2658        let snapshot = multibuffer.read(cx).snapshot(cx);
2659        assert_eq!(snapshot.text(), "abc");
2660    }
2661
2662    #[gpui::test]
2663    fn test_excerpt_buffer(cx: &mut MutableAppContext) {
2664        let buffer_1 = cx.add_model(|cx| Buffer::new(0, sample_text(6, 6, 'a'), cx));
2665        let buffer_2 = cx.add_model(|cx| Buffer::new(0, sample_text(6, 6, 'g'), cx));
2666        let multibuffer = cx.add_model(|_| MultiBuffer::new(0));
2667
2668        let subscription = multibuffer.update(cx, |multibuffer, cx| {
2669            let subscription = multibuffer.subscribe();
2670            multibuffer.push_excerpt(buffer_1.clone(), Point::new(1, 2)..Point::new(2, 5), cx);
2671            assert_eq!(
2672                subscription.consume().into_inner(),
2673                [Edit {
2674                    old: 0..0,
2675                    new: 0..10
2676                }]
2677            );
2678
2679            multibuffer.push_excerpt(buffer_1.clone(), Point::new(3, 3)..Point::new(4, 4), cx);
2680            multibuffer.push_excerpt(buffer_2.clone(), Point::new(3, 1)..Point::new(3, 3), cx);
2681            assert_eq!(
2682                subscription.consume().into_inner(),
2683                [Edit {
2684                    old: 10..10,
2685                    new: 10..22
2686                }]
2687            );
2688
2689            subscription
2690        });
2691
2692        let snapshot = multibuffer.read(cx).snapshot(cx);
2693        assert_eq!(
2694            snapshot.text(),
2695            concat!(
2696                "bbbb\n",  // Preserve newlines
2697                "ccccc\n", //
2698                "ddd\n",   //
2699                "eeee\n",  //
2700                "jj"       //
2701            )
2702        );
2703        assert_eq!(
2704            snapshot.buffer_rows(0).collect::<Vec<_>>(),
2705            [Some(1), Some(2), Some(3), Some(4), Some(3)]
2706        );
2707        assert_eq!(
2708            snapshot.buffer_rows(2).collect::<Vec<_>>(),
2709            [Some(3), Some(4), Some(3)]
2710        );
2711        assert_eq!(snapshot.buffer_rows(4).collect::<Vec<_>>(), [Some(3)]);
2712        assert_eq!(snapshot.buffer_rows(5).collect::<Vec<_>>(), []);
2713
2714        assert_eq!(
2715            boundaries_in_range(Point::new(0, 0)..Point::new(4, 2), &snapshot),
2716            &[
2717                (0, "bbbb\nccccc".to_string(), true),
2718                (2, "ddd\neeee".to_string(), false),
2719                (4, "jj".to_string(), true),
2720            ]
2721        );
2722        assert_eq!(
2723            boundaries_in_range(Point::new(0, 0)..Point::new(2, 0), &snapshot),
2724            &[(0, "bbbb\nccccc".to_string(), true)]
2725        );
2726        assert_eq!(
2727            boundaries_in_range(Point::new(1, 0)..Point::new(1, 5), &snapshot),
2728            &[]
2729        );
2730        assert_eq!(
2731            boundaries_in_range(Point::new(1, 0)..Point::new(2, 0), &snapshot),
2732            &[]
2733        );
2734        assert_eq!(
2735            boundaries_in_range(Point::new(1, 0)..Point::new(4, 0), &snapshot),
2736            &[(2, "ddd\neeee".to_string(), false)]
2737        );
2738        assert_eq!(
2739            boundaries_in_range(Point::new(1, 0)..Point::new(4, 0), &snapshot),
2740            &[(2, "ddd\neeee".to_string(), false)]
2741        );
2742        assert_eq!(
2743            boundaries_in_range(Point::new(2, 0)..Point::new(3, 0), &snapshot),
2744            &[(2, "ddd\neeee".to_string(), false)]
2745        );
2746        assert_eq!(
2747            boundaries_in_range(Point::new(4, 0)..Point::new(4, 2), &snapshot),
2748            &[(4, "jj".to_string(), true)]
2749        );
2750        assert_eq!(
2751            boundaries_in_range(Point::new(4, 2)..Point::new(4, 2), &snapshot),
2752            &[]
2753        );
2754
2755        buffer_1.update(cx, |buffer, cx| {
2756            buffer.edit(
2757                [
2758                    Point::new(0, 0)..Point::new(0, 0),
2759                    Point::new(2, 1)..Point::new(2, 3),
2760                ],
2761                "\n",
2762                cx,
2763            );
2764        });
2765
2766        let snapshot = multibuffer.read(cx).snapshot(cx);
2767        assert_eq!(
2768            snapshot.text(),
2769            concat!(
2770                "bbbb\n", // Preserve newlines
2771                "c\n",    //
2772                "cc\n",   //
2773                "ddd\n",  //
2774                "eeee\n", //
2775                "jj"      //
2776            )
2777        );
2778
2779        assert_eq!(
2780            subscription.consume().into_inner(),
2781            [Edit {
2782                old: 6..8,
2783                new: 6..7
2784            }]
2785        );
2786
2787        let snapshot = multibuffer.read(cx).snapshot(cx);
2788        assert_eq!(
2789            snapshot.clip_point(Point::new(0, 5), Bias::Left),
2790            Point::new(0, 4)
2791        );
2792        assert_eq!(
2793            snapshot.clip_point(Point::new(0, 5), Bias::Right),
2794            Point::new(0, 4)
2795        );
2796        assert_eq!(
2797            snapshot.clip_point(Point::new(5, 1), Bias::Right),
2798            Point::new(5, 1)
2799        );
2800        assert_eq!(
2801            snapshot.clip_point(Point::new(5, 2), Bias::Right),
2802            Point::new(5, 2)
2803        );
2804        assert_eq!(
2805            snapshot.clip_point(Point::new(5, 3), Bias::Right),
2806            Point::new(5, 2)
2807        );
2808
2809        let snapshot = multibuffer.update(cx, |multibuffer, cx| {
2810            let buffer_2_excerpt_id = multibuffer.excerpt_ids_for_buffer(&buffer_2)[0].clone();
2811            multibuffer.remove_excerpts(&[buffer_2_excerpt_id], cx);
2812            multibuffer.snapshot(cx)
2813        });
2814
2815        assert_eq!(
2816            snapshot.text(),
2817            concat!(
2818                "bbbb\n", // Preserve newlines
2819                "c\n",    //
2820                "cc\n",   //
2821                "ddd\n",  //
2822                "eeee",   //
2823            )
2824        );
2825
2826        fn boundaries_in_range(
2827            range: Range<Point>,
2828            snapshot: &MultiBufferSnapshot,
2829        ) -> Vec<(u32, String, bool)> {
2830            snapshot
2831                .excerpt_boundaries_in_range(range)
2832                .map(|boundary| {
2833                    (
2834                        boundary.row,
2835                        boundary
2836                            .buffer
2837                            .text_for_range(boundary.range)
2838                            .collect::<String>(),
2839                        boundary.starts_new_buffer,
2840                    )
2841                })
2842                .collect::<Vec<_>>()
2843        }
2844    }
2845
2846    #[gpui::test]
2847    fn test_empty_excerpt_buffer(cx: &mut MutableAppContext) {
2848        let multibuffer = cx.add_model(|_| MultiBuffer::new(0));
2849
2850        let snapshot = multibuffer.read(cx).snapshot(cx);
2851        assert_eq!(snapshot.text(), "");
2852        assert_eq!(snapshot.buffer_rows(0).collect::<Vec<_>>(), &[Some(0)]);
2853        assert_eq!(snapshot.buffer_rows(1).collect::<Vec<_>>(), &[]);
2854    }
2855
2856    #[gpui::test]
2857    fn test_singleton_multibuffer_anchors(cx: &mut MutableAppContext) {
2858        let buffer = cx.add_model(|cx| Buffer::new(0, "abcd", cx));
2859        let multibuffer = cx.add_model(|cx| MultiBuffer::singleton(buffer.clone(), cx));
2860        let old_snapshot = multibuffer.read(cx).snapshot(cx);
2861        buffer.update(cx, |buffer, cx| {
2862            buffer.edit([0..0], "X", cx);
2863            buffer.edit([5..5], "Y", cx);
2864        });
2865        let new_snapshot = multibuffer.read(cx).snapshot(cx);
2866
2867        assert_eq!(old_snapshot.text(), "abcd");
2868        assert_eq!(new_snapshot.text(), "XabcdY");
2869
2870        assert_eq!(old_snapshot.anchor_before(0).to_offset(&new_snapshot), 0);
2871        assert_eq!(old_snapshot.anchor_after(0).to_offset(&new_snapshot), 1);
2872        assert_eq!(old_snapshot.anchor_before(4).to_offset(&new_snapshot), 5);
2873        assert_eq!(old_snapshot.anchor_after(4).to_offset(&new_snapshot), 6);
2874    }
2875
2876    #[gpui::test]
2877    fn test_multibuffer_anchors(cx: &mut MutableAppContext) {
2878        let buffer_1 = cx.add_model(|cx| Buffer::new(0, "abcd", cx));
2879        let buffer_2 = cx.add_model(|cx| Buffer::new(0, "efghi", cx));
2880        let multibuffer = cx.add_model(|cx| {
2881            let mut multibuffer = MultiBuffer::new(0);
2882            multibuffer.push_excerpt(buffer_1.clone(), 0..4, cx);
2883            multibuffer.push_excerpt(buffer_2.clone(), 0..5, cx);
2884            multibuffer
2885        });
2886        let old_snapshot = multibuffer.read(cx).snapshot(cx);
2887
2888        assert_eq!(old_snapshot.anchor_before(0).to_offset(&old_snapshot), 0);
2889        assert_eq!(old_snapshot.anchor_after(0).to_offset(&old_snapshot), 0);
2890        assert_eq!(Anchor::min().to_offset(&old_snapshot), 0);
2891        assert_eq!(Anchor::min().to_offset(&old_snapshot), 0);
2892        assert_eq!(Anchor::max().to_offset(&old_snapshot), 10);
2893        assert_eq!(Anchor::max().to_offset(&old_snapshot), 10);
2894
2895        buffer_1.update(cx, |buffer, cx| {
2896            buffer.edit([0..0], "W", cx);
2897            buffer.edit([5..5], "X", cx);
2898        });
2899        buffer_2.update(cx, |buffer, cx| {
2900            buffer.edit([0..0], "Y", cx);
2901            buffer.edit([6..0], "Z", cx);
2902        });
2903        let new_snapshot = multibuffer.read(cx).snapshot(cx);
2904
2905        assert_eq!(old_snapshot.text(), "abcd\nefghi");
2906        assert_eq!(new_snapshot.text(), "WabcdX\nYefghiZ");
2907
2908        assert_eq!(old_snapshot.anchor_before(0).to_offset(&new_snapshot), 0);
2909        assert_eq!(old_snapshot.anchor_after(0).to_offset(&new_snapshot), 1);
2910        assert_eq!(old_snapshot.anchor_before(1).to_offset(&new_snapshot), 2);
2911        assert_eq!(old_snapshot.anchor_after(1).to_offset(&new_snapshot), 2);
2912        assert_eq!(old_snapshot.anchor_before(2).to_offset(&new_snapshot), 3);
2913        assert_eq!(old_snapshot.anchor_after(2).to_offset(&new_snapshot), 3);
2914        assert_eq!(old_snapshot.anchor_before(5).to_offset(&new_snapshot), 7);
2915        assert_eq!(old_snapshot.anchor_after(5).to_offset(&new_snapshot), 8);
2916        assert_eq!(old_snapshot.anchor_before(10).to_offset(&new_snapshot), 13);
2917        assert_eq!(old_snapshot.anchor_after(10).to_offset(&new_snapshot), 14);
2918    }
2919
2920    #[gpui::test]
2921    fn test_multibuffer_resolving_anchors_after_replacing_their_excerpts(
2922        cx: &mut MutableAppContext,
2923    ) {
2924        let buffer_1 = cx.add_model(|cx| Buffer::new(0, "abcd", cx));
2925        let buffer_2 = cx.add_model(|cx| Buffer::new(0, "ABCDEFGHIJKLMNOP", cx));
2926        let multibuffer = cx.add_model(|_| MultiBuffer::new(0));
2927
2928        // Create an insertion id in buffer 1 that doesn't exist in buffer 2.
2929        // Add an excerpt from buffer 1 that spans this new insertion.
2930        buffer_1.update(cx, |buffer, cx| buffer.edit([4..4], "123", cx));
2931        let excerpt_id_1 = multibuffer.update(cx, |multibuffer, cx| {
2932            multibuffer.push_excerpt(buffer_1.clone(), 0..7, cx)
2933        });
2934
2935        let snapshot_1 = multibuffer.read(cx).snapshot(cx);
2936        assert_eq!(snapshot_1.text(), "abcd123");
2937
2938        // Replace the buffer 1 excerpt with new excerpts from buffer 2.
2939        let (excerpt_id_2, excerpt_id_3, _) = multibuffer.update(cx, |multibuffer, cx| {
2940            multibuffer.remove_excerpts([&excerpt_id_1], cx);
2941            (
2942                multibuffer.push_excerpt(buffer_2.clone(), 0..4, cx),
2943                multibuffer.push_excerpt(buffer_2.clone(), 6..10, cx),
2944                multibuffer.push_excerpt(buffer_2.clone(), 12..16, cx),
2945            )
2946        });
2947        let snapshot_2 = multibuffer.read(cx).snapshot(cx);
2948        assert_eq!(snapshot_2.text(), "ABCD\nGHIJ\nMNOP");
2949
2950        // The old excerpt id has been reused.
2951        assert_eq!(excerpt_id_2, excerpt_id_1);
2952
2953        // Resolve some anchors from the previous snapshot in the new snapshot.
2954        // Although there is still an excerpt with the same id, it is for
2955        // a different buffer, so we don't attempt to resolve the old text
2956        // anchor in the new buffer.
2957        assert_eq!(
2958            snapshot_2.summary_for_anchor::<usize>(&snapshot_1.anchor_before(2)),
2959            0
2960        );
2961        assert_eq!(
2962            snapshot_2.summaries_for_anchors::<usize, _>(&[
2963                snapshot_1.anchor_before(2),
2964                snapshot_1.anchor_after(3)
2965            ]),
2966            vec![0, 0]
2967        );
2968        let refresh =
2969            snapshot_2.refresh_anchors(&[snapshot_1.anchor_before(2), snapshot_1.anchor_after(3)]);
2970        assert_eq!(
2971            refresh,
2972            &[
2973                (0, snapshot_2.anchor_before(0), false),
2974                (1, snapshot_2.anchor_after(0), false),
2975            ]
2976        );
2977
2978        // Replace the middle excerpt with a smaller excerpt in buffer 2,
2979        // that intersects the old excerpt.
2980        let excerpt_id_5 = multibuffer.update(cx, |multibuffer, cx| {
2981            multibuffer.remove_excerpts([&excerpt_id_3], cx);
2982            multibuffer.insert_excerpt_after(&excerpt_id_3, buffer_2.clone(), 5..8, cx)
2983        });
2984
2985        let snapshot_3 = multibuffer.read(cx).snapshot(cx);
2986        assert_eq!(snapshot_3.text(), "ABCD\nFGH\nMNOP");
2987        assert_ne!(excerpt_id_5, excerpt_id_3);
2988
2989        // Resolve some anchors from the previous snapshot in the new snapshot.
2990        // The anchor in the middle excerpt snaps to the beginning of the
2991        // excerpt, since it is not
2992        let anchors = [
2993            snapshot_2.anchor_before(0),
2994            snapshot_2.anchor_after(2),
2995            snapshot_2.anchor_after(6),
2996            snapshot_2.anchor_after(14),
2997        ];
2998        assert_eq!(
2999            snapshot_3.summaries_for_anchors::<usize, _>(&anchors),
3000            &[0, 2, 9, 13]
3001        );
3002
3003        let new_anchors = snapshot_3.refresh_anchors(&anchors);
3004        assert_eq!(
3005            new_anchors.iter().map(|a| (a.0, a.2)).collect::<Vec<_>>(),
3006            &[(0, true), (1, true), (2, true), (3, true)]
3007        );
3008        assert_eq!(
3009            snapshot_3.summaries_for_anchors::<usize, _>(new_anchors.iter().map(|a| &a.1)),
3010            &[0, 2, 7, 13]
3011        );
3012    }
3013
3014    #[gpui::test(iterations = 100)]
3015    fn test_random_multibuffer(cx: &mut MutableAppContext, mut rng: StdRng) {
3016        let operations = env::var("OPERATIONS")
3017            .map(|i| i.parse().expect("invalid `OPERATIONS` variable"))
3018            .unwrap_or(10);
3019
3020        let mut buffers: Vec<ModelHandle<Buffer>> = Vec::new();
3021        let multibuffer = cx.add_model(|_| MultiBuffer::new(0));
3022        let mut excerpt_ids = Vec::new();
3023        let mut expected_excerpts = Vec::<(ModelHandle<Buffer>, Range<text::Anchor>)>::new();
3024        let mut anchors = Vec::new();
3025        let mut old_versions = Vec::new();
3026
3027        for _ in 0..operations {
3028            match rng.gen_range(0..100) {
3029                0..=19 if !buffers.is_empty() => {
3030                    let buffer = buffers.choose(&mut rng).unwrap();
3031                    buffer.update(cx, |buf, cx| buf.randomly_edit(&mut rng, 5, cx));
3032                }
3033                20..=29 if !expected_excerpts.is_empty() => {
3034                    let mut ids_to_remove = vec![];
3035                    for _ in 0..rng.gen_range(1..=3) {
3036                        if expected_excerpts.is_empty() {
3037                            break;
3038                        }
3039
3040                        let ix = rng.gen_range(0..expected_excerpts.len());
3041                        ids_to_remove.push(excerpt_ids.remove(ix));
3042                        let (buffer, range) = expected_excerpts.remove(ix);
3043                        let buffer = buffer.read(cx);
3044                        log::info!(
3045                            "Removing excerpt {}: {:?}",
3046                            ix,
3047                            buffer
3048                                .text_for_range(range.to_offset(&buffer))
3049                                .collect::<String>(),
3050                        );
3051                    }
3052                    ids_to_remove.sort_unstable();
3053                    multibuffer.update(cx, |multibuffer, cx| {
3054                        multibuffer.remove_excerpts(&ids_to_remove, cx)
3055                    });
3056                }
3057                30..=39 if !expected_excerpts.is_empty() => {
3058                    let multibuffer = multibuffer.read(cx).read(cx);
3059                    let offset =
3060                        multibuffer.clip_offset(rng.gen_range(0..=multibuffer.len()), Bias::Left);
3061                    let bias = if rng.gen() { Bias::Left } else { Bias::Right };
3062                    log::info!("Creating anchor at {} with bias {:?}", offset, bias);
3063                    anchors.push(multibuffer.anchor_at(offset, bias));
3064                    anchors.sort_by(|a, b| a.cmp(&b, &multibuffer).unwrap());
3065                }
3066                40..=44 if !anchors.is_empty() => {
3067                    let multibuffer = multibuffer.read(cx).read(cx);
3068
3069                    anchors = multibuffer
3070                        .refresh_anchors(&anchors)
3071                        .into_iter()
3072                        .map(|a| a.1)
3073                        .collect();
3074
3075                    // Ensure the newly-refreshed anchors point to a valid excerpt and don't
3076                    // overshoot its boundaries.
3077                    let mut cursor = multibuffer.excerpts.cursor::<Option<&ExcerptId>>();
3078                    for anchor in &anchors {
3079                        if anchor.excerpt_id == ExcerptId::min()
3080                            || anchor.excerpt_id == ExcerptId::max()
3081                        {
3082                            continue;
3083                        }
3084
3085                        cursor.seek_forward(&Some(&anchor.excerpt_id), Bias::Left, &());
3086                        let excerpt = cursor.item().unwrap();
3087                        assert_eq!(excerpt.id, anchor.excerpt_id);
3088                        assert!(excerpt.contains(anchor));
3089                    }
3090                }
3091                _ => {
3092                    let buffer_handle = if buffers.is_empty() || rng.gen_bool(0.4) {
3093                        let base_text = RandomCharIter::new(&mut rng).take(10).collect::<String>();
3094                        buffers.push(cx.add_model(|cx| Buffer::new(0, base_text, cx)));
3095                        buffers.last().unwrap()
3096                    } else {
3097                        buffers.choose(&mut rng).unwrap()
3098                    };
3099
3100                    let buffer = buffer_handle.read(cx);
3101                    let end_ix = buffer.clip_offset(rng.gen_range(0..=buffer.len()), Bias::Right);
3102                    let start_ix = buffer.clip_offset(rng.gen_range(0..=end_ix), Bias::Left);
3103                    let anchor_range = buffer.anchor_before(start_ix)..buffer.anchor_after(end_ix);
3104                    let prev_excerpt_ix = rng.gen_range(0..=expected_excerpts.len());
3105                    let prev_excerpt_id = excerpt_ids
3106                        .get(prev_excerpt_ix)
3107                        .cloned()
3108                        .unwrap_or(ExcerptId::max());
3109                    let excerpt_ix = (prev_excerpt_ix + 1).min(expected_excerpts.len());
3110
3111                    log::info!(
3112                        "Inserting excerpt at {} of {} for buffer {}: {:?}[{:?}] = {:?}",
3113                        excerpt_ix,
3114                        expected_excerpts.len(),
3115                        buffer_handle.id(),
3116                        buffer.text(),
3117                        start_ix..end_ix,
3118                        &buffer.text()[start_ix..end_ix]
3119                    );
3120
3121                    let excerpt_id = multibuffer.update(cx, |multibuffer, cx| {
3122                        multibuffer.insert_excerpt_after(
3123                            &prev_excerpt_id,
3124                            buffer_handle.clone(),
3125                            start_ix..end_ix,
3126                            cx,
3127                        )
3128                    });
3129
3130                    excerpt_ids.insert(excerpt_ix, excerpt_id);
3131                    expected_excerpts.insert(excerpt_ix, (buffer_handle.clone(), anchor_range));
3132                }
3133            }
3134
3135            if rng.gen_bool(0.3) {
3136                multibuffer.update(cx, |multibuffer, cx| {
3137                    old_versions.push((multibuffer.snapshot(cx), multibuffer.subscribe()));
3138                })
3139            }
3140
3141            let snapshot = multibuffer.read(cx).snapshot(cx);
3142
3143            let mut excerpt_starts = Vec::new();
3144            let mut expected_text = String::new();
3145            let mut expected_buffer_rows = Vec::new();
3146            for (buffer, range) in &expected_excerpts {
3147                let buffer = buffer.read(cx);
3148                let buffer_range = range.to_offset(buffer);
3149
3150                excerpt_starts.push(TextSummary::from(expected_text.as_str()));
3151                expected_text.extend(buffer.text_for_range(buffer_range.clone()));
3152                expected_text.push('\n');
3153
3154                let buffer_row_range = buffer.offset_to_point(buffer_range.start).row
3155                    ..=buffer.offset_to_point(buffer_range.end).row;
3156                for row in buffer_row_range {
3157                    expected_buffer_rows.push(Some(row));
3158                }
3159            }
3160            // Remove final trailing newline.
3161            if !expected_excerpts.is_empty() {
3162                expected_text.pop();
3163            }
3164
3165            // Always report one buffer row
3166            if expected_buffer_rows.is_empty() {
3167                expected_buffer_rows.push(Some(0));
3168            }
3169
3170            assert_eq!(snapshot.text(), expected_text);
3171            log::info!("MultiBuffer text: {:?}", expected_text);
3172
3173            assert_eq!(
3174                snapshot.buffer_rows(0).collect::<Vec<_>>(),
3175                expected_buffer_rows,
3176            );
3177
3178            for _ in 0..5 {
3179                let start_row = rng.gen_range(0..=expected_buffer_rows.len());
3180                assert_eq!(
3181                    snapshot.buffer_rows(start_row as u32).collect::<Vec<_>>(),
3182                    &expected_buffer_rows[start_row..],
3183                    "buffer_rows({})",
3184                    start_row
3185                );
3186            }
3187
3188            assert_eq!(
3189                snapshot.max_buffer_row(),
3190                expected_buffer_rows
3191                    .into_iter()
3192                    .filter_map(|r| r)
3193                    .max()
3194                    .unwrap()
3195            );
3196
3197            let mut excerpt_starts = excerpt_starts.into_iter();
3198            for (buffer, range) in &expected_excerpts {
3199                let buffer_id = buffer.id();
3200                let buffer = buffer.read(cx);
3201                let buffer_range = range.to_offset(buffer);
3202                let buffer_start_point = buffer.offset_to_point(buffer_range.start);
3203                let buffer_start_point_utf16 =
3204                    buffer.text_summary_for_range::<PointUtf16, _>(0..buffer_range.start);
3205
3206                let excerpt_start = excerpt_starts.next().unwrap();
3207                let mut offset = excerpt_start.bytes;
3208                let mut buffer_offset = buffer_range.start;
3209                let mut point = excerpt_start.lines;
3210                let mut buffer_point = buffer_start_point;
3211                let mut point_utf16 = excerpt_start.lines_utf16;
3212                let mut buffer_point_utf16 = buffer_start_point_utf16;
3213                for ch in buffer
3214                    .snapshot()
3215                    .chunks(buffer_range.clone(), false)
3216                    .flat_map(|c| c.text.chars())
3217                {
3218                    for _ in 0..ch.len_utf8() {
3219                        let left_offset = snapshot.clip_offset(offset, Bias::Left);
3220                        let right_offset = snapshot.clip_offset(offset, Bias::Right);
3221                        let buffer_left_offset = buffer.clip_offset(buffer_offset, Bias::Left);
3222                        let buffer_right_offset = buffer.clip_offset(buffer_offset, Bias::Right);
3223                        assert_eq!(
3224                            left_offset,
3225                            excerpt_start.bytes + (buffer_left_offset - buffer_range.start),
3226                            "clip_offset({:?}, Left). buffer: {:?}, buffer offset: {:?}",
3227                            offset,
3228                            buffer_id,
3229                            buffer_offset,
3230                        );
3231                        assert_eq!(
3232                            right_offset,
3233                            excerpt_start.bytes + (buffer_right_offset - buffer_range.start),
3234                            "clip_offset({:?}, Right). buffer: {:?}, buffer offset: {:?}",
3235                            offset,
3236                            buffer_id,
3237                            buffer_offset,
3238                        );
3239
3240                        let left_point = snapshot.clip_point(point, Bias::Left);
3241                        let right_point = snapshot.clip_point(point, Bias::Right);
3242                        let buffer_left_point = buffer.clip_point(buffer_point, Bias::Left);
3243                        let buffer_right_point = buffer.clip_point(buffer_point, Bias::Right);
3244                        assert_eq!(
3245                            left_point,
3246                            excerpt_start.lines + (buffer_left_point - buffer_start_point),
3247                            "clip_point({:?}, Left). buffer: {:?}, buffer point: {:?}",
3248                            point,
3249                            buffer_id,
3250                            buffer_point,
3251                        );
3252                        assert_eq!(
3253                            right_point,
3254                            excerpt_start.lines + (buffer_right_point - buffer_start_point),
3255                            "clip_point({:?}, Right). buffer: {:?}, buffer point: {:?}",
3256                            point,
3257                            buffer_id,
3258                            buffer_point,
3259                        );
3260
3261                        assert_eq!(
3262                            snapshot.point_to_offset(left_point),
3263                            left_offset,
3264                            "point_to_offset({:?})",
3265                            left_point,
3266                        );
3267                        assert_eq!(
3268                            snapshot.offset_to_point(left_offset),
3269                            left_point,
3270                            "offset_to_point({:?})",
3271                            left_offset,
3272                        );
3273
3274                        offset += 1;
3275                        buffer_offset += 1;
3276                        if ch == '\n' {
3277                            point += Point::new(1, 0);
3278                            buffer_point += Point::new(1, 0);
3279                        } else {
3280                            point += Point::new(0, 1);
3281                            buffer_point += Point::new(0, 1);
3282                        }
3283                    }
3284
3285                    for _ in 0..ch.len_utf16() {
3286                        let left_point_utf16 = snapshot.clip_point_utf16(point_utf16, Bias::Left);
3287                        let right_point_utf16 = snapshot.clip_point_utf16(point_utf16, Bias::Right);
3288                        let buffer_left_point_utf16 =
3289                            buffer.clip_point_utf16(buffer_point_utf16, Bias::Left);
3290                        let buffer_right_point_utf16 =
3291                            buffer.clip_point_utf16(buffer_point_utf16, Bias::Right);
3292                        assert_eq!(
3293                            left_point_utf16,
3294                            excerpt_start.lines_utf16
3295                                + (buffer_left_point_utf16 - buffer_start_point_utf16),
3296                            "clip_point_utf16({:?}, Left). buffer: {:?}, buffer point_utf16: {:?}",
3297                            point_utf16,
3298                            buffer_id,
3299                            buffer_point_utf16,
3300                        );
3301                        assert_eq!(
3302                            right_point_utf16,
3303                            excerpt_start.lines_utf16
3304                                + (buffer_right_point_utf16 - buffer_start_point_utf16),
3305                            "clip_point_utf16({:?}, Right). buffer: {:?}, buffer point_utf16: {:?}",
3306                            point_utf16,
3307                            buffer_id,
3308                            buffer_point_utf16,
3309                        );
3310
3311                        if ch == '\n' {
3312                            point_utf16 += PointUtf16::new(1, 0);
3313                            buffer_point_utf16 += PointUtf16::new(1, 0);
3314                        } else {
3315                            point_utf16 += PointUtf16::new(0, 1);
3316                            buffer_point_utf16 += PointUtf16::new(0, 1);
3317                        }
3318                    }
3319                }
3320            }
3321
3322            for (row, line) in expected_text.split('\n').enumerate() {
3323                assert_eq!(
3324                    snapshot.line_len(row as u32),
3325                    line.len() as u32,
3326                    "line_len({}).",
3327                    row
3328                );
3329            }
3330
3331            let text_rope = Rope::from(expected_text.as_str());
3332            for _ in 0..10 {
3333                let end_ix = text_rope.clip_offset(rng.gen_range(0..=text_rope.len()), Bias::Right);
3334                let start_ix = text_rope.clip_offset(rng.gen_range(0..=end_ix), Bias::Left);
3335
3336                let text_for_range = snapshot
3337                    .text_for_range(start_ix..end_ix)
3338                    .collect::<String>();
3339                assert_eq!(
3340                    text_for_range,
3341                    &expected_text[start_ix..end_ix],
3342                    "incorrect text for range {:?}",
3343                    start_ix..end_ix
3344                );
3345
3346                let excerpted_buffer_ranges =
3347                    multibuffer.read(cx).excerpted_buffers(start_ix..end_ix, cx);
3348                let excerpted_buffers_text = excerpted_buffer_ranges
3349                    .into_iter()
3350                    .map(|(buffer, buffer_range)| {
3351                        buffer
3352                            .read(cx)
3353                            .text_for_range(buffer_range)
3354                            .collect::<String>()
3355                    })
3356                    .collect::<Vec<_>>()
3357                    .join("\n");
3358                assert_eq!(excerpted_buffers_text, text_for_range);
3359
3360                let expected_summary = TextSummary::from(&expected_text[start_ix..end_ix]);
3361                assert_eq!(
3362                    snapshot.text_summary_for_range::<TextSummary, _>(start_ix..end_ix),
3363                    expected_summary,
3364                    "incorrect summary for range {:?}",
3365                    start_ix..end_ix
3366                );
3367            }
3368
3369            // Anchor resolution
3370            for (anchor, resolved_offset) in anchors
3371                .iter()
3372                .zip(snapshot.summaries_for_anchors::<usize, _>(&anchors))
3373            {
3374                assert!(resolved_offset <= snapshot.len());
3375                assert_eq!(
3376                    snapshot.summary_for_anchor::<usize>(anchor),
3377                    resolved_offset
3378                );
3379            }
3380
3381            for _ in 0..10 {
3382                let end_ix = text_rope.clip_offset(rng.gen_range(0..=text_rope.len()), Bias::Right);
3383                assert_eq!(
3384                    snapshot.reversed_chars_at(end_ix).collect::<String>(),
3385                    expected_text[..end_ix].chars().rev().collect::<String>(),
3386                );
3387            }
3388
3389            for _ in 0..10 {
3390                let end_ix = rng.gen_range(0..=text_rope.len());
3391                let start_ix = rng.gen_range(0..=end_ix);
3392                assert_eq!(
3393                    snapshot
3394                        .bytes_in_range(start_ix..end_ix)
3395                        .flatten()
3396                        .copied()
3397                        .collect::<Vec<_>>(),
3398                    expected_text.as_bytes()[start_ix..end_ix].to_vec(),
3399                    "bytes_in_range({:?})",
3400                    start_ix..end_ix,
3401                );
3402            }
3403        }
3404
3405        let snapshot = multibuffer.read(cx).snapshot(cx);
3406        for (old_snapshot, subscription) in old_versions {
3407            let edits = subscription.consume().into_inner();
3408
3409            log::info!(
3410                "applying subscription edits to old text: {:?}: {:?}",
3411                old_snapshot.text(),
3412                edits,
3413            );
3414
3415            let mut text = old_snapshot.text();
3416            for edit in edits {
3417                let new_text: String = snapshot.text_for_range(edit.new.clone()).collect();
3418                text.replace_range(edit.new.start..edit.new.start + edit.old.len(), &new_text);
3419            }
3420            assert_eq!(text.to_string(), snapshot.text());
3421        }
3422    }
3423
3424    #[gpui::test]
3425    fn test_history(cx: &mut MutableAppContext) {
3426        let buffer_1 = cx.add_model(|cx| Buffer::new(0, "1234", cx));
3427        let buffer_2 = cx.add_model(|cx| Buffer::new(0, "5678", cx));
3428        let multibuffer = cx.add_model(|_| MultiBuffer::new(0));
3429        let group_interval = multibuffer.read(cx).history.group_interval;
3430        multibuffer.update(cx, |multibuffer, cx| {
3431            multibuffer.push_excerpt(buffer_1.clone(), 0..buffer_1.read(cx).len(), cx);
3432            multibuffer.push_excerpt(buffer_2.clone(), 0..buffer_2.read(cx).len(), cx);
3433        });
3434
3435        let mut now = Instant::now();
3436
3437        multibuffer.update(cx, |multibuffer, cx| {
3438            multibuffer.start_transaction_at(now, cx);
3439            multibuffer.edit(
3440                [
3441                    Point::new(0, 0)..Point::new(0, 0),
3442                    Point::new(1, 0)..Point::new(1, 0),
3443                ],
3444                "A",
3445                cx,
3446            );
3447            multibuffer.edit(
3448                [
3449                    Point::new(0, 1)..Point::new(0, 1),
3450                    Point::new(1, 1)..Point::new(1, 1),
3451                ],
3452                "B",
3453                cx,
3454            );
3455            multibuffer.end_transaction_at(now, cx);
3456            assert_eq!(multibuffer.read(cx).text(), "AB1234\nAB5678");
3457
3458            now += 2 * group_interval;
3459            multibuffer.start_transaction_at(now, cx);
3460            multibuffer.edit([2..2], "C", cx);
3461            multibuffer.end_transaction_at(now, cx);
3462            assert_eq!(multibuffer.read(cx).text(), "ABC1234\nAB5678");
3463
3464            multibuffer.undo(cx);
3465            assert_eq!(multibuffer.read(cx).text(), "AB1234\nAB5678");
3466
3467            multibuffer.undo(cx);
3468            assert_eq!(multibuffer.read(cx).text(), "1234\n5678");
3469
3470            multibuffer.redo(cx);
3471            assert_eq!(multibuffer.read(cx).text(), "AB1234\nAB5678");
3472
3473            multibuffer.redo(cx);
3474            assert_eq!(multibuffer.read(cx).text(), "ABC1234\nAB5678");
3475
3476            buffer_1.update(cx, |buffer_1, cx| buffer_1.undo(cx));
3477            assert_eq!(multibuffer.read(cx).text(), "AB1234\nAB5678");
3478
3479            multibuffer.undo(cx);
3480            assert_eq!(multibuffer.read(cx).text(), "1234\n5678");
3481
3482            multibuffer.redo(cx);
3483            assert_eq!(multibuffer.read(cx).text(), "AB1234\nAB5678");
3484
3485            multibuffer.redo(cx);
3486            assert_eq!(multibuffer.read(cx).text(), "ABC1234\nAB5678");
3487
3488            multibuffer.undo(cx);
3489            assert_eq!(multibuffer.read(cx).text(), "AB1234\nAB5678");
3490
3491            buffer_1.update(cx, |buffer_1, cx| buffer_1.redo(cx));
3492            assert_eq!(multibuffer.read(cx).text(), "ABC1234\nAB5678");
3493
3494            multibuffer.undo(cx);
3495            assert_eq!(multibuffer.read(cx).text(), "C1234\n5678");
3496        });
3497    }
3498}