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