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