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