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