multi_buffer.rs

   1mod anchor;
   2
   3pub use anchor::{Anchor, AnchorRangeExt};
   4use anyhow::Result;
   5use clock::ReplicaId;
   6use collections::{Bound, HashMap, HashSet};
   7use gpui::{AppContext, Entity, ModelContext, ModelHandle, Task};
   8pub use language::Completion;
   9use language::{
  10    char_kind, Buffer, BufferChunks, BufferSnapshot, CharKind, Chunk, DiagnosticEntry, Event, File,
  11    Language, OffsetRangeExt, Outline, OutlineItem, Selection, ToOffset as _, ToPoint as _,
  12    ToPointUtf16 as _, TransactionId,
  13};
  14use std::{
  15    cell::{Ref, RefCell},
  16    cmp, fmt, io,
  17    iter::{self, FromIterator},
  18    ops::{Range, RangeBounds, Sub},
  19    str,
  20    sync::Arc,
  21    time::{Duration, Instant},
  22};
  23use sum_tree::{Bias, Cursor, SumTree};
  24use text::{
  25    locator::Locator,
  26    rope::TextDimension,
  27    subscription::{Subscription, Topic},
  28    Edit, Point, PointUtf16, TextSummary,
  29};
  30use theme::SyntaxTheme;
  31
  32const NEWLINES: &'static [u8] = &[b'\n'; u8::MAX as usize];
  33
  34pub type ExcerptId = Locator;
  35
  36pub struct MultiBuffer {
  37    snapshot: RefCell<MultiBufferSnapshot>,
  38    buffers: RefCell<HashMap<usize, BufferState>>,
  39    subscriptions: Topic,
  40    singleton: bool,
  41    replica_id: ReplicaId,
  42    history: History,
  43    title: Option<String>,
  44}
  45
  46#[derive(Clone)]
  47struct History {
  48    next_transaction_id: TransactionId,
  49    undo_stack: Vec<Transaction>,
  50    redo_stack: Vec<Transaction>,
  51    transaction_depth: usize,
  52    group_interval: Duration,
  53}
  54
  55#[derive(Clone)]
  56struct Transaction {
  57    id: TransactionId,
  58    buffer_transactions: HashMap<usize, text::TransactionId>,
  59    first_edit_at: Instant,
  60    last_edit_at: Instant,
  61    suppress_grouping: bool,
  62}
  63
  64pub trait ToOffset: 'static + fmt::Debug {
  65    fn to_offset(&self, snapshot: &MultiBufferSnapshot) -> usize;
  66}
  67
  68pub trait ToPoint: 'static + fmt::Debug {
  69    fn to_point(&self, snapshot: &MultiBufferSnapshot) -> Point;
  70}
  71
  72pub trait ToPointUtf16: 'static + fmt::Debug {
  73    fn to_point_utf16(&self, snapshot: &MultiBufferSnapshot) -> PointUtf16;
  74}
  75
  76struct BufferState {
  77    buffer: ModelHandle<Buffer>,
  78    last_version: clock::Global,
  79    last_parse_count: usize,
  80    last_selections_update_count: usize,
  81    last_diagnostics_update_count: usize,
  82    last_file_update_count: usize,
  83    excerpts: Vec<ExcerptId>,
  84    _subscriptions: [gpui::Subscription; 2],
  85}
  86
  87#[derive(Clone, Default)]
  88pub struct MultiBufferSnapshot {
  89    singleton: bool,
  90    excerpts: SumTree<Excerpt>,
  91    parse_count: usize,
  92    diagnostics_update_count: usize,
  93    trailing_excerpt_update_count: usize,
  94    is_dirty: bool,
  95    has_conflict: bool,
  96}
  97
  98pub struct ExcerptBoundary {
  99    pub id: ExcerptId,
 100    pub row: u32,
 101    pub buffer: BufferSnapshot,
 102    pub range: Range<text::Anchor>,
 103    pub starts_new_buffer: bool,
 104}
 105
 106#[derive(Clone)]
 107struct Excerpt {
 108    id: ExcerptId,
 109    buffer_id: usize,
 110    buffer: BufferSnapshot,
 111    range: Range<text::Anchor>,
 112    max_buffer_row: u32,
 113    text_summary: TextSummary,
 114    has_trailing_newline: bool,
 115}
 116
 117#[derive(Clone, Debug, Default)]
 118struct ExcerptSummary {
 119    excerpt_id: ExcerptId,
 120    max_buffer_row: u32,
 121    text: TextSummary,
 122}
 123
 124pub struct MultiBufferRows<'a> {
 125    buffer_row_range: Range<u32>,
 126    excerpts: Cursor<'a, Excerpt, Point>,
 127}
 128
 129pub struct MultiBufferChunks<'a> {
 130    range: Range<usize>,
 131    excerpts: Cursor<'a, Excerpt, usize>,
 132    excerpt_chunks: Option<ExcerptChunks<'a>>,
 133    language_aware: bool,
 134}
 135
 136pub struct MultiBufferBytes<'a> {
 137    range: Range<usize>,
 138    excerpts: Cursor<'a, Excerpt, usize>,
 139    excerpt_bytes: Option<ExcerptBytes<'a>>,
 140    chunk: &'a [u8],
 141}
 142
 143struct ExcerptChunks<'a> {
 144    content_chunks: BufferChunks<'a>,
 145    footer_height: usize,
 146}
 147
 148struct ExcerptBytes<'a> {
 149    content_bytes: language::rope::Bytes<'a>,
 150    footer_height: usize,
 151}
 152
 153impl MultiBuffer {
 154    pub fn new(replica_id: ReplicaId) -> Self {
 155        Self {
 156            snapshot: Default::default(),
 157            buffers: Default::default(),
 158            subscriptions: Default::default(),
 159            singleton: false,
 160            replica_id,
 161            history: History {
 162                next_transaction_id: Default::default(),
 163                undo_stack: Default::default(),
 164                redo_stack: Default::default(),
 165                transaction_depth: 0,
 166                group_interval: Duration::from_millis(300),
 167            },
 168            title: Default::default(),
 169        }
 170    }
 171
 172    pub fn clone(&self, new_cx: &mut ModelContext<Self>) -> Self {
 173        let mut buffers = HashMap::default();
 174        for (buffer_id, buffer_state) in self.buffers.borrow().iter() {
 175            buffers.insert(
 176                *buffer_id,
 177                BufferState {
 178                    buffer: buffer_state.buffer.clone(),
 179                    last_version: buffer_state.last_version.clone(),
 180                    last_parse_count: buffer_state.last_parse_count,
 181                    last_selections_update_count: buffer_state.last_selections_update_count,
 182                    last_diagnostics_update_count: buffer_state.last_diagnostics_update_count,
 183                    last_file_update_count: buffer_state.last_file_update_count,
 184                    excerpts: buffer_state.excerpts.clone(),
 185                    _subscriptions: [
 186                        new_cx.observe(&buffer_state.buffer, |_, _, cx| cx.notify()),
 187                        new_cx.subscribe(&buffer_state.buffer, Self::on_buffer_event),
 188                    ],
 189                },
 190            );
 191        }
 192        Self {
 193            snapshot: RefCell::new(self.snapshot.borrow().clone()),
 194            buffers: RefCell::new(buffers),
 195            subscriptions: Default::default(),
 196            singleton: self.singleton,
 197            replica_id: self.replica_id,
 198            history: self.history.clone(),
 199            title: self.title.clone(),
 200        }
 201    }
 202
 203    pub fn with_title(mut self, title: String) -> Self {
 204        self.title = Some(title);
 205        self
 206    }
 207
 208    pub fn singleton(buffer: ModelHandle<Buffer>, cx: &mut ModelContext<Self>) -> Self {
 209        let mut this = Self::new(buffer.read(cx).replica_id());
 210        this.singleton = true;
 211        this.push_excerpts(buffer, [text::Anchor::min()..text::Anchor::max()], cx);
 212        this.snapshot.borrow_mut().singleton = true;
 213        this
 214    }
 215
 216    #[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    pub 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(excerpt) = self.excerpt(&anchor.excerpt_id) {
2002            anchor.buffer_id == Some(excerpt.buffer_id)
2003                && excerpt.buffer.can_resolve(&anchor.text_anchor)
2004        } else {
2005            false
2006        }
2007    }
2008
2009    pub fn excerpt_boundaries_in_range<'a, R, T>(
2010        &'a self,
2011        range: R,
2012    ) -> impl Iterator<Item = ExcerptBoundary> + 'a
2013    where
2014        R: RangeBounds<T>,
2015        T: ToOffset,
2016    {
2017        let start_offset;
2018        let start = match range.start_bound() {
2019            Bound::Included(start) => {
2020                start_offset = start.to_offset(self);
2021                Bound::Included(start_offset)
2022            }
2023            Bound::Excluded(start) => {
2024                start_offset = start.to_offset(self);
2025                Bound::Excluded(start_offset)
2026            }
2027            Bound::Unbounded => {
2028                start_offset = 0;
2029                Bound::Unbounded
2030            }
2031        };
2032        let end = match range.end_bound() {
2033            Bound::Included(end) => Bound::Included(end.to_offset(self)),
2034            Bound::Excluded(end) => Bound::Excluded(end.to_offset(self)),
2035            Bound::Unbounded => Bound::Unbounded,
2036        };
2037        let bounds = (start, end);
2038
2039        let mut cursor = self.excerpts.cursor::<(usize, Point)>();
2040        cursor.seek(&start_offset, Bias::Right, &());
2041        if cursor.item().is_none() {
2042            cursor.prev(&());
2043        }
2044        if !bounds.contains(&cursor.start().0) {
2045            cursor.next(&());
2046        }
2047
2048        let mut prev_buffer_id = cursor.prev_item().map(|excerpt| excerpt.buffer_id);
2049        std::iter::from_fn(move || {
2050            if self.singleton {
2051                None
2052            } else if bounds.contains(&cursor.start().0) {
2053                let excerpt = cursor.item()?;
2054                let starts_new_buffer = Some(excerpt.buffer_id) != prev_buffer_id;
2055                let boundary = ExcerptBoundary {
2056                    id: excerpt.id.clone(),
2057                    row: cursor.start().1.row,
2058                    buffer: excerpt.buffer.clone(),
2059                    range: excerpt.range.clone(),
2060                    starts_new_buffer,
2061                };
2062
2063                prev_buffer_id = Some(excerpt.buffer_id);
2064                cursor.next(&());
2065                Some(boundary)
2066            } else {
2067                None
2068            }
2069        })
2070    }
2071
2072    pub fn parse_count(&self) -> usize {
2073        self.parse_count
2074    }
2075
2076    pub fn enclosing_bracket_ranges<T: ToOffset>(
2077        &self,
2078        range: Range<T>,
2079    ) -> Option<(Range<usize>, Range<usize>)> {
2080        let range = range.start.to_offset(self)..range.end.to_offset(self);
2081
2082        let mut cursor = self.excerpts.cursor::<usize>();
2083        cursor.seek(&range.start, Bias::Right, &());
2084        let start_excerpt = cursor.item();
2085
2086        cursor.seek(&range.end, Bias::Right, &());
2087        let end_excerpt = cursor.item();
2088
2089        start_excerpt
2090            .zip(end_excerpt)
2091            .and_then(|(start_excerpt, end_excerpt)| {
2092                if start_excerpt.id != end_excerpt.id {
2093                    return None;
2094                }
2095
2096                let excerpt_buffer_start =
2097                    start_excerpt.range.start.to_offset(&start_excerpt.buffer);
2098                let excerpt_buffer_end = excerpt_buffer_start + start_excerpt.text_summary.bytes;
2099
2100                let start_in_buffer =
2101                    excerpt_buffer_start + range.start.saturating_sub(*cursor.start());
2102                let end_in_buffer =
2103                    excerpt_buffer_start + range.end.saturating_sub(*cursor.start());
2104                let (mut start_bracket_range, mut end_bracket_range) = start_excerpt
2105                    .buffer
2106                    .enclosing_bracket_ranges(start_in_buffer..end_in_buffer)?;
2107
2108                if start_bracket_range.start >= excerpt_buffer_start
2109                    && end_bracket_range.end < excerpt_buffer_end
2110                {
2111                    start_bracket_range.start =
2112                        cursor.start() + (start_bracket_range.start - excerpt_buffer_start);
2113                    start_bracket_range.end =
2114                        cursor.start() + (start_bracket_range.end - excerpt_buffer_start);
2115                    end_bracket_range.start =
2116                        cursor.start() + (end_bracket_range.start - excerpt_buffer_start);
2117                    end_bracket_range.end =
2118                        cursor.start() + (end_bracket_range.end - excerpt_buffer_start);
2119                    Some((start_bracket_range, end_bracket_range))
2120                } else {
2121                    None
2122                }
2123            })
2124    }
2125
2126    pub fn diagnostics_update_count(&self) -> usize {
2127        self.diagnostics_update_count
2128    }
2129
2130    pub fn trailing_excerpt_update_count(&self) -> usize {
2131        self.trailing_excerpt_update_count
2132    }
2133
2134    pub fn language(&self) -> Option<&Arc<Language>> {
2135        self.excerpts
2136            .iter()
2137            .next()
2138            .and_then(|excerpt| excerpt.buffer.language())
2139    }
2140
2141    pub fn is_dirty(&self) -> bool {
2142        self.is_dirty
2143    }
2144
2145    pub fn has_conflict(&self) -> bool {
2146        self.has_conflict
2147    }
2148
2149    pub fn diagnostic_group<'a, O>(
2150        &'a self,
2151        group_id: usize,
2152    ) -> impl Iterator<Item = DiagnosticEntry<O>> + 'a
2153    where
2154        O: text::FromAnchor + 'a,
2155    {
2156        self.as_singleton()
2157            .into_iter()
2158            .flat_map(move |(_, _, buffer)| buffer.diagnostic_group(group_id))
2159    }
2160
2161    pub fn diagnostics_in_range<'a, T, O>(
2162        &'a self,
2163        range: Range<T>,
2164    ) -> impl Iterator<Item = DiagnosticEntry<O>> + 'a
2165    where
2166        T: 'a + ToOffset,
2167        O: 'a + text::FromAnchor,
2168    {
2169        self.as_singleton()
2170            .into_iter()
2171            .flat_map(move |(_, _, buffer)| {
2172                buffer.diagnostics_in_range(range.start.to_offset(self)..range.end.to_offset(self))
2173            })
2174    }
2175
2176    pub fn range_for_syntax_ancestor<T: ToOffset>(&self, range: Range<T>) -> Option<Range<usize>> {
2177        let range = range.start.to_offset(self)..range.end.to_offset(self);
2178
2179        let mut cursor = self.excerpts.cursor::<usize>();
2180        cursor.seek(&range.start, Bias::Right, &());
2181        let start_excerpt = cursor.item();
2182
2183        cursor.seek(&range.end, Bias::Right, &());
2184        let end_excerpt = cursor.item();
2185
2186        start_excerpt
2187            .zip(end_excerpt)
2188            .and_then(|(start_excerpt, end_excerpt)| {
2189                if start_excerpt.id != end_excerpt.id {
2190                    return None;
2191                }
2192
2193                let excerpt_buffer_start =
2194                    start_excerpt.range.start.to_offset(&start_excerpt.buffer);
2195                let excerpt_buffer_end = excerpt_buffer_start + start_excerpt.text_summary.bytes;
2196
2197                let start_in_buffer =
2198                    excerpt_buffer_start + range.start.saturating_sub(*cursor.start());
2199                let end_in_buffer =
2200                    excerpt_buffer_start + range.end.saturating_sub(*cursor.start());
2201                let mut ancestor_buffer_range = start_excerpt
2202                    .buffer
2203                    .range_for_syntax_ancestor(start_in_buffer..end_in_buffer)?;
2204                ancestor_buffer_range.start =
2205                    cmp::max(ancestor_buffer_range.start, excerpt_buffer_start);
2206                ancestor_buffer_range.end = cmp::min(ancestor_buffer_range.end, excerpt_buffer_end);
2207
2208                let start = cursor.start() + (ancestor_buffer_range.start - excerpt_buffer_start);
2209                let end = cursor.start() + (ancestor_buffer_range.end - excerpt_buffer_start);
2210                Some(start..end)
2211            })
2212    }
2213
2214    pub fn outline(&self, theme: Option<&SyntaxTheme>) -> Option<Outline<Anchor>> {
2215        let (excerpt_id, _, buffer) = self.as_singleton()?;
2216        let outline = buffer.outline(theme)?;
2217        Some(Outline::new(
2218            outline
2219                .items
2220                .into_iter()
2221                .map(|item| OutlineItem {
2222                    depth: item.depth,
2223                    range: self.anchor_in_excerpt(excerpt_id.clone(), item.range.start)
2224                        ..self.anchor_in_excerpt(excerpt_id.clone(), item.range.end),
2225                    text: item.text,
2226                    highlight_ranges: item.highlight_ranges,
2227                    name_ranges: item.name_ranges,
2228                })
2229                .collect(),
2230        ))
2231    }
2232
2233    fn excerpt<'a>(&'a self, excerpt_id: &'a ExcerptId) -> Option<&'a Excerpt> {
2234        let mut cursor = self.excerpts.cursor::<Option<&ExcerptId>>();
2235        cursor.seek(&Some(excerpt_id), Bias::Left, &());
2236        if let Some(excerpt) = cursor.item() {
2237            if excerpt.id == *excerpt_id {
2238                return Some(excerpt);
2239            }
2240        }
2241        None
2242    }
2243
2244    pub fn remote_selections_in_range<'a>(
2245        &'a self,
2246        range: &'a Range<Anchor>,
2247    ) -> impl 'a + Iterator<Item = (ReplicaId, Selection<Anchor>)> {
2248        let mut cursor = self.excerpts.cursor::<Option<&ExcerptId>>();
2249        cursor.seek(&Some(&range.start.excerpt_id), Bias::Left, &());
2250        cursor
2251            .take_while(move |excerpt| excerpt.id <= range.end.excerpt_id)
2252            .flat_map(move |excerpt| {
2253                let mut query_range = excerpt.range.start.clone()..excerpt.range.end.clone();
2254                if excerpt.id == range.start.excerpt_id {
2255                    query_range.start = range.start.text_anchor.clone();
2256                }
2257                if excerpt.id == range.end.excerpt_id {
2258                    query_range.end = range.end.text_anchor.clone();
2259                }
2260
2261                excerpt
2262                    .buffer
2263                    .remote_selections_in_range(query_range)
2264                    .flat_map(move |(replica_id, selections)| {
2265                        selections.map(move |selection| {
2266                            let mut start = Anchor {
2267                                buffer_id: Some(excerpt.buffer_id),
2268                                excerpt_id: excerpt.id.clone(),
2269                                text_anchor: selection.start.clone(),
2270                            };
2271                            let mut end = Anchor {
2272                                buffer_id: Some(excerpt.buffer_id),
2273                                excerpt_id: excerpt.id.clone(),
2274                                text_anchor: selection.end.clone(),
2275                            };
2276                            if range.start.cmp(&start, self).unwrap().is_gt() {
2277                                start = range.start.clone();
2278                            }
2279                            if range.end.cmp(&end, self).unwrap().is_lt() {
2280                                end = range.end.clone();
2281                            }
2282
2283                            (
2284                                replica_id,
2285                                Selection {
2286                                    id: selection.id,
2287                                    start,
2288                                    end,
2289                                    reversed: selection.reversed,
2290                                    goal: selection.goal,
2291                                },
2292                            )
2293                        })
2294                    })
2295            })
2296    }
2297}
2298
2299impl History {
2300    fn start_transaction(&mut self, now: Instant) -> Option<TransactionId> {
2301        self.transaction_depth += 1;
2302        if self.transaction_depth == 1 {
2303            let id = self.next_transaction_id.tick();
2304            self.undo_stack.push(Transaction {
2305                id,
2306                buffer_transactions: Default::default(),
2307                first_edit_at: now,
2308                last_edit_at: now,
2309                suppress_grouping: false,
2310            });
2311            Some(id)
2312        } else {
2313            None
2314        }
2315    }
2316
2317    fn end_transaction(
2318        &mut self,
2319        now: Instant,
2320        buffer_transactions: HashMap<usize, TransactionId>,
2321    ) -> bool {
2322        assert_ne!(self.transaction_depth, 0);
2323        self.transaction_depth -= 1;
2324        if self.transaction_depth == 0 {
2325            if buffer_transactions.is_empty() {
2326                self.undo_stack.pop();
2327                false
2328            } else {
2329                let transaction = self.undo_stack.last_mut().unwrap();
2330                transaction.last_edit_at = now;
2331                for (buffer_id, transaction_id) in buffer_transactions {
2332                    transaction
2333                        .buffer_transactions
2334                        .entry(buffer_id)
2335                        .or_insert(transaction_id);
2336                }
2337                true
2338            }
2339        } else {
2340            false
2341        }
2342    }
2343
2344    fn push_transaction<'a, T>(&mut self, buffer_transactions: T, now: Instant)
2345    where
2346        T: IntoIterator<Item = (&'a ModelHandle<Buffer>, &'a language::Transaction)>,
2347    {
2348        assert_eq!(self.transaction_depth, 0);
2349        let transaction = Transaction {
2350            id: self.next_transaction_id.tick(),
2351            buffer_transactions: buffer_transactions
2352                .into_iter()
2353                .map(|(buffer, transaction)| (buffer.id(), transaction.id))
2354                .collect(),
2355            first_edit_at: now,
2356            last_edit_at: now,
2357            suppress_grouping: false,
2358        };
2359        if !transaction.buffer_transactions.is_empty() {
2360            self.undo_stack.push(transaction);
2361        }
2362    }
2363
2364    fn finalize_last_transaction(&mut self) {
2365        if let Some(transaction) = self.undo_stack.last_mut() {
2366            transaction.suppress_grouping = true;
2367        }
2368    }
2369
2370    fn pop_undo(&mut self) -> Option<&mut Transaction> {
2371        assert_eq!(self.transaction_depth, 0);
2372        if let Some(transaction) = self.undo_stack.pop() {
2373            self.redo_stack.push(transaction);
2374            self.redo_stack.last_mut()
2375        } else {
2376            None
2377        }
2378    }
2379
2380    fn pop_redo(&mut self) -> Option<&mut Transaction> {
2381        assert_eq!(self.transaction_depth, 0);
2382        if let Some(transaction) = self.redo_stack.pop() {
2383            self.undo_stack.push(transaction);
2384            self.undo_stack.last_mut()
2385        } else {
2386            None
2387        }
2388    }
2389
2390    fn group(&mut self) -> Option<TransactionId> {
2391        let mut new_len = self.undo_stack.len();
2392        let mut transactions = self.undo_stack.iter_mut();
2393
2394        if let Some(mut transaction) = transactions.next_back() {
2395            while let Some(prev_transaction) = transactions.next_back() {
2396                if !prev_transaction.suppress_grouping
2397                    && transaction.first_edit_at - prev_transaction.last_edit_at
2398                        <= self.group_interval
2399                {
2400                    transaction = prev_transaction;
2401                    new_len -= 1;
2402                } else {
2403                    break;
2404                }
2405            }
2406        }
2407
2408        let (transactions_to_keep, transactions_to_merge) = self.undo_stack.split_at_mut(new_len);
2409        if let Some(last_transaction) = transactions_to_keep.last_mut() {
2410            if let Some(transaction) = transactions_to_merge.last() {
2411                last_transaction.last_edit_at = transaction.last_edit_at;
2412            }
2413            for to_merge in transactions_to_merge {
2414                for (buffer_id, transaction_id) in &to_merge.buffer_transactions {
2415                    last_transaction
2416                        .buffer_transactions
2417                        .entry(*buffer_id)
2418                        .or_insert(*transaction_id);
2419                }
2420            }
2421        }
2422
2423        self.undo_stack.truncate(new_len);
2424        self.undo_stack.last().map(|t| t.id)
2425    }
2426}
2427
2428impl Excerpt {
2429    fn new(
2430        id: ExcerptId,
2431        buffer_id: usize,
2432        buffer: BufferSnapshot,
2433        range: Range<text::Anchor>,
2434        has_trailing_newline: bool,
2435    ) -> Self {
2436        Excerpt {
2437            id,
2438            max_buffer_row: range.end.to_point(&buffer).row,
2439            text_summary: buffer.text_summary_for_range::<TextSummary, _>(range.to_offset(&buffer)),
2440            buffer_id,
2441            buffer,
2442            range,
2443            has_trailing_newline,
2444        }
2445    }
2446
2447    fn chunks_in_range<'a>(
2448        &'a self,
2449        range: Range<usize>,
2450        language_aware: bool,
2451    ) -> ExcerptChunks<'a> {
2452        let content_start = self.range.start.to_offset(&self.buffer);
2453        let chunks_start = content_start + range.start;
2454        let chunks_end = content_start + cmp::min(range.end, self.text_summary.bytes);
2455
2456        let footer_height = if self.has_trailing_newline
2457            && range.start <= self.text_summary.bytes
2458            && range.end > self.text_summary.bytes
2459        {
2460            1
2461        } else {
2462            0
2463        };
2464
2465        let content_chunks = self.buffer.chunks(chunks_start..chunks_end, language_aware);
2466
2467        ExcerptChunks {
2468            content_chunks,
2469            footer_height,
2470        }
2471    }
2472
2473    fn bytes_in_range(&self, range: Range<usize>) -> ExcerptBytes {
2474        let content_start = self.range.start.to_offset(&self.buffer);
2475        let bytes_start = content_start + range.start;
2476        let bytes_end = content_start + cmp::min(range.end, self.text_summary.bytes);
2477        let footer_height = if self.has_trailing_newline
2478            && range.start <= self.text_summary.bytes
2479            && range.end > self.text_summary.bytes
2480        {
2481            1
2482        } else {
2483            0
2484        };
2485        let content_bytes = self.buffer.bytes_in_range(bytes_start..bytes_end);
2486
2487        ExcerptBytes {
2488            content_bytes,
2489            footer_height,
2490        }
2491    }
2492
2493    fn clip_anchor(&self, text_anchor: text::Anchor) -> text::Anchor {
2494        if text_anchor
2495            .cmp(&self.range.start, &self.buffer)
2496            .unwrap()
2497            .is_lt()
2498        {
2499            self.range.start.clone()
2500        } else if text_anchor
2501            .cmp(&self.range.end, &self.buffer)
2502            .unwrap()
2503            .is_gt()
2504        {
2505            self.range.end.clone()
2506        } else {
2507            text_anchor
2508        }
2509    }
2510
2511    fn contains(&self, anchor: &Anchor) -> bool {
2512        Some(self.buffer_id) == anchor.buffer_id
2513            && self
2514                .range
2515                .start
2516                .cmp(&anchor.text_anchor, &self.buffer)
2517                .unwrap()
2518                .is_le()
2519            && self
2520                .range
2521                .end
2522                .cmp(&anchor.text_anchor, &self.buffer)
2523                .unwrap()
2524                .is_ge()
2525    }
2526}
2527
2528impl fmt::Debug for Excerpt {
2529    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2530        f.debug_struct("Excerpt")
2531            .field("id", &self.id)
2532            .field("buffer_id", &self.buffer_id)
2533            .field("range", &self.range)
2534            .field("text_summary", &self.text_summary)
2535            .field("has_trailing_newline", &self.has_trailing_newline)
2536            .finish()
2537    }
2538}
2539
2540impl sum_tree::Item for Excerpt {
2541    type Summary = ExcerptSummary;
2542
2543    fn summary(&self) -> Self::Summary {
2544        let mut text = self.text_summary.clone();
2545        if self.has_trailing_newline {
2546            text += TextSummary::from("\n");
2547        }
2548        ExcerptSummary {
2549            excerpt_id: self.id.clone(),
2550            max_buffer_row: self.max_buffer_row,
2551            text,
2552        }
2553    }
2554}
2555
2556impl sum_tree::Summary for ExcerptSummary {
2557    type Context = ();
2558
2559    fn add_summary(&mut self, summary: &Self, _: &()) {
2560        debug_assert!(summary.excerpt_id > self.excerpt_id);
2561        self.excerpt_id = summary.excerpt_id.clone();
2562        self.text.add_summary(&summary.text, &());
2563        self.max_buffer_row = cmp::max(self.max_buffer_row, summary.max_buffer_row);
2564    }
2565}
2566
2567impl<'a> sum_tree::Dimension<'a, ExcerptSummary> for TextSummary {
2568    fn add_summary(&mut self, summary: &'a ExcerptSummary, _: &()) {
2569        *self += &summary.text;
2570    }
2571}
2572
2573impl<'a> sum_tree::Dimension<'a, ExcerptSummary> for usize {
2574    fn add_summary(&mut self, summary: &'a ExcerptSummary, _: &()) {
2575        *self += summary.text.bytes;
2576    }
2577}
2578
2579impl<'a> sum_tree::SeekTarget<'a, ExcerptSummary, ExcerptSummary> for usize {
2580    fn cmp(&self, cursor_location: &ExcerptSummary, _: &()) -> cmp::Ordering {
2581        Ord::cmp(self, &cursor_location.text.bytes)
2582    }
2583}
2584
2585impl<'a> sum_tree::SeekTarget<'a, ExcerptSummary, ExcerptSummary> for Option<&'a ExcerptId> {
2586    fn cmp(&self, cursor_location: &ExcerptSummary, _: &()) -> cmp::Ordering {
2587        Ord::cmp(self, &Some(&cursor_location.excerpt_id))
2588    }
2589}
2590
2591impl<'a> sum_tree::Dimension<'a, ExcerptSummary> for Point {
2592    fn add_summary(&mut self, summary: &'a ExcerptSummary, _: &()) {
2593        *self += summary.text.lines;
2594    }
2595}
2596
2597impl<'a> sum_tree::Dimension<'a, ExcerptSummary> for PointUtf16 {
2598    fn add_summary(&mut self, summary: &'a ExcerptSummary, _: &()) {
2599        *self += summary.text.lines_utf16
2600    }
2601}
2602
2603impl<'a> sum_tree::Dimension<'a, ExcerptSummary> for Option<&'a ExcerptId> {
2604    fn add_summary(&mut self, summary: &'a ExcerptSummary, _: &()) {
2605        *self = Some(&summary.excerpt_id);
2606    }
2607}
2608
2609impl<'a> MultiBufferRows<'a> {
2610    pub fn seek(&mut self, row: u32) {
2611        self.buffer_row_range = 0..0;
2612
2613        self.excerpts
2614            .seek_forward(&Point::new(row, 0), Bias::Right, &());
2615        if self.excerpts.item().is_none() {
2616            self.excerpts.prev(&());
2617
2618            if self.excerpts.item().is_none() && row == 0 {
2619                self.buffer_row_range = 0..1;
2620                return;
2621            }
2622        }
2623
2624        if let Some(excerpt) = self.excerpts.item() {
2625            let overshoot = row - self.excerpts.start().row;
2626            let excerpt_start = excerpt.range.start.to_point(&excerpt.buffer).row;
2627            self.buffer_row_range.start = excerpt_start + overshoot;
2628            self.buffer_row_range.end = excerpt_start + excerpt.text_summary.lines.row + 1;
2629        }
2630    }
2631}
2632
2633impl<'a> Iterator for MultiBufferRows<'a> {
2634    type Item = Option<u32>;
2635
2636    fn next(&mut self) -> Option<Self::Item> {
2637        loop {
2638            if !self.buffer_row_range.is_empty() {
2639                let row = Some(self.buffer_row_range.start);
2640                self.buffer_row_range.start += 1;
2641                return Some(row);
2642            }
2643            self.excerpts.item()?;
2644            self.excerpts.next(&());
2645            let excerpt = self.excerpts.item()?;
2646            self.buffer_row_range.start = excerpt.range.start.to_point(&excerpt.buffer).row;
2647            self.buffer_row_range.end =
2648                self.buffer_row_range.start + excerpt.text_summary.lines.row + 1;
2649        }
2650    }
2651}
2652
2653impl<'a> MultiBufferChunks<'a> {
2654    pub fn offset(&self) -> usize {
2655        self.range.start
2656    }
2657
2658    pub fn seek(&mut self, offset: usize) {
2659        self.range.start = offset;
2660        self.excerpts.seek(&offset, Bias::Right, &());
2661        if let Some(excerpt) = self.excerpts.item() {
2662            self.excerpt_chunks = Some(excerpt.chunks_in_range(
2663                self.range.start - self.excerpts.start()..self.range.end - self.excerpts.start(),
2664                self.language_aware,
2665            ));
2666        } else {
2667            self.excerpt_chunks = None;
2668        }
2669    }
2670}
2671
2672impl<'a> Iterator for MultiBufferChunks<'a> {
2673    type Item = Chunk<'a>;
2674
2675    fn next(&mut self) -> Option<Self::Item> {
2676        if self.range.is_empty() {
2677            None
2678        } else if let Some(chunk) = self.excerpt_chunks.as_mut()?.next() {
2679            self.range.start += chunk.text.len();
2680            Some(chunk)
2681        } else {
2682            self.excerpts.next(&());
2683            let excerpt = self.excerpts.item()?;
2684            self.excerpt_chunks = Some(excerpt.chunks_in_range(
2685                0..self.range.end - self.excerpts.start(),
2686                self.language_aware,
2687            ));
2688            self.next()
2689        }
2690    }
2691}
2692
2693impl<'a> MultiBufferBytes<'a> {
2694    fn consume(&mut self, len: usize) {
2695        self.range.start += len;
2696        self.chunk = &self.chunk[len..];
2697
2698        if !self.range.is_empty() && self.chunk.is_empty() {
2699            if let Some(chunk) = self.excerpt_bytes.as_mut().and_then(|bytes| bytes.next()) {
2700                self.chunk = chunk;
2701            } else {
2702                self.excerpts.next(&());
2703                if let Some(excerpt) = self.excerpts.item() {
2704                    let mut excerpt_bytes =
2705                        excerpt.bytes_in_range(0..self.range.end - self.excerpts.start());
2706                    self.chunk = excerpt_bytes.next().unwrap();
2707                    self.excerpt_bytes = Some(excerpt_bytes);
2708                }
2709            }
2710        }
2711    }
2712}
2713
2714impl<'a> Iterator for MultiBufferBytes<'a> {
2715    type Item = &'a [u8];
2716
2717    fn next(&mut self) -> Option<Self::Item> {
2718        let chunk = self.chunk;
2719        if chunk.is_empty() {
2720            None
2721        } else {
2722            self.consume(chunk.len());
2723            Some(chunk)
2724        }
2725    }
2726}
2727
2728impl<'a> io::Read for MultiBufferBytes<'a> {
2729    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
2730        let len = cmp::min(buf.len(), self.chunk.len());
2731        buf[..len].copy_from_slice(&self.chunk[..len]);
2732        if len > 0 {
2733            self.consume(len);
2734        }
2735        Ok(len)
2736    }
2737}
2738
2739impl<'a> Iterator for ExcerptBytes<'a> {
2740    type Item = &'a [u8];
2741
2742    fn next(&mut self) -> Option<Self::Item> {
2743        if let Some(chunk) = self.content_bytes.next() {
2744            if !chunk.is_empty() {
2745                return Some(chunk);
2746            }
2747        }
2748
2749        if self.footer_height > 0 {
2750            let result = &NEWLINES[..self.footer_height];
2751            self.footer_height = 0;
2752            return Some(result);
2753        }
2754
2755        None
2756    }
2757}
2758
2759impl<'a> Iterator for ExcerptChunks<'a> {
2760    type Item = Chunk<'a>;
2761
2762    fn next(&mut self) -> Option<Self::Item> {
2763        if let Some(chunk) = self.content_chunks.next() {
2764            return Some(chunk);
2765        }
2766
2767        if self.footer_height > 0 {
2768            let text = unsafe { str::from_utf8_unchecked(&NEWLINES[..self.footer_height]) };
2769            self.footer_height = 0;
2770            return Some(Chunk {
2771                text,
2772                ..Default::default()
2773            });
2774        }
2775
2776        None
2777    }
2778}
2779
2780impl ToOffset for Point {
2781    fn to_offset<'a>(&self, snapshot: &MultiBufferSnapshot) -> usize {
2782        snapshot.point_to_offset(*self)
2783    }
2784}
2785
2786impl ToOffset for PointUtf16 {
2787    fn to_offset<'a>(&self, snapshot: &MultiBufferSnapshot) -> usize {
2788        snapshot.point_utf16_to_offset(*self)
2789    }
2790}
2791
2792impl ToOffset for usize {
2793    fn to_offset<'a>(&self, snapshot: &MultiBufferSnapshot) -> usize {
2794        assert!(*self <= snapshot.len(), "offset is out of range");
2795        *self
2796    }
2797}
2798
2799impl ToPoint for usize {
2800    fn to_point<'a>(&self, snapshot: &MultiBufferSnapshot) -> Point {
2801        snapshot.offset_to_point(*self)
2802    }
2803}
2804
2805impl ToPoint for Point {
2806    fn to_point<'a>(&self, _: &MultiBufferSnapshot) -> Point {
2807        *self
2808    }
2809}
2810
2811impl ToPointUtf16 for usize {
2812    fn to_point_utf16<'a>(&self, snapshot: &MultiBufferSnapshot) -> PointUtf16 {
2813        snapshot.offset_to_point_utf16(*self)
2814    }
2815}
2816
2817impl ToPointUtf16 for Point {
2818    fn to_point_utf16<'a>(&self, snapshot: &MultiBufferSnapshot) -> PointUtf16 {
2819        snapshot.point_to_point_utf16(*self)
2820    }
2821}
2822
2823impl ToPointUtf16 for PointUtf16 {
2824    fn to_point_utf16<'a>(&self, _: &MultiBufferSnapshot) -> PointUtf16 {
2825        *self
2826    }
2827}
2828
2829#[cfg(test)]
2830mod tests {
2831    use super::*;
2832    use gpui::MutableAppContext;
2833    use language::{Buffer, Rope};
2834    use rand::prelude::*;
2835    use std::env;
2836    use text::{Point, RandomCharIter};
2837    use util::test::sample_text;
2838
2839    #[gpui::test]
2840    fn test_singleton_multibuffer(cx: &mut MutableAppContext) {
2841        let buffer = cx.add_model(|cx| Buffer::new(0, sample_text(6, 6, 'a'), cx));
2842        let multibuffer = cx.add_model(|cx| MultiBuffer::singleton(buffer.clone(), cx));
2843
2844        let snapshot = multibuffer.read(cx).snapshot(cx);
2845        assert_eq!(snapshot.text(), buffer.read(cx).text());
2846
2847        assert_eq!(
2848            snapshot.buffer_rows(0).collect::<Vec<_>>(),
2849            (0..buffer.read(cx).row_count())
2850                .map(Some)
2851                .collect::<Vec<_>>()
2852        );
2853
2854        buffer.update(cx, |buffer, cx| buffer.edit([1..3], "XXX\n", cx));
2855        let snapshot = multibuffer.read(cx).snapshot(cx);
2856
2857        assert_eq!(snapshot.text(), buffer.read(cx).text());
2858        assert_eq!(
2859            snapshot.buffer_rows(0).collect::<Vec<_>>(),
2860            (0..buffer.read(cx).row_count())
2861                .map(Some)
2862                .collect::<Vec<_>>()
2863        );
2864    }
2865
2866    #[gpui::test]
2867    fn test_remote_multibuffer(cx: &mut MutableAppContext) {
2868        let host_buffer = cx.add_model(|cx| Buffer::new(0, "a", cx));
2869        let guest_buffer = cx.add_model(|cx| {
2870            let message = host_buffer.read(cx).to_proto();
2871            Buffer::from_proto(1, message, None, cx).unwrap()
2872        });
2873        let multibuffer = cx.add_model(|cx| MultiBuffer::singleton(guest_buffer.clone(), cx));
2874        let snapshot = multibuffer.read(cx).snapshot(cx);
2875        assert_eq!(snapshot.text(), "a");
2876
2877        guest_buffer.update(cx, |buffer, cx| buffer.edit([1..1], "b", cx));
2878        let snapshot = multibuffer.read(cx).snapshot(cx);
2879        assert_eq!(snapshot.text(), "ab");
2880
2881        guest_buffer.update(cx, |buffer, cx| buffer.edit([2..2], "c", cx));
2882        let snapshot = multibuffer.read(cx).snapshot(cx);
2883        assert_eq!(snapshot.text(), "abc");
2884    }
2885
2886    #[gpui::test]
2887    fn test_excerpt_buffer(cx: &mut MutableAppContext) {
2888        let buffer_1 = cx.add_model(|cx| Buffer::new(0, sample_text(6, 6, 'a'), cx));
2889        let buffer_2 = cx.add_model(|cx| Buffer::new(0, sample_text(6, 6, 'g'), cx));
2890        let multibuffer = cx.add_model(|_| MultiBuffer::new(0));
2891
2892        let subscription = multibuffer.update(cx, |multibuffer, cx| {
2893            let subscription = multibuffer.subscribe();
2894            multibuffer.push_excerpts(buffer_1.clone(), [Point::new(1, 2)..Point::new(2, 5)], cx);
2895            assert_eq!(
2896                subscription.consume().into_inner(),
2897                [Edit {
2898                    old: 0..0,
2899                    new: 0..10
2900                }]
2901            );
2902
2903            multibuffer.push_excerpts(buffer_1.clone(), [Point::new(3, 3)..Point::new(4, 4)], cx);
2904            multibuffer.push_excerpts(buffer_2.clone(), [Point::new(3, 1)..Point::new(3, 3)], cx);
2905            assert_eq!(
2906                subscription.consume().into_inner(),
2907                [Edit {
2908                    old: 10..10,
2909                    new: 10..22
2910                }]
2911            );
2912
2913            subscription
2914        });
2915
2916        let snapshot = multibuffer.read(cx).snapshot(cx);
2917        assert_eq!(
2918            snapshot.text(),
2919            concat!(
2920                "bbbb\n",  // Preserve newlines
2921                "ccccc\n", //
2922                "ddd\n",   //
2923                "eeee\n",  //
2924                "jj"       //
2925            )
2926        );
2927        assert_eq!(
2928            snapshot.buffer_rows(0).collect::<Vec<_>>(),
2929            [Some(1), Some(2), Some(3), Some(4), Some(3)]
2930        );
2931        assert_eq!(
2932            snapshot.buffer_rows(2).collect::<Vec<_>>(),
2933            [Some(3), Some(4), Some(3)]
2934        );
2935        assert_eq!(snapshot.buffer_rows(4).collect::<Vec<_>>(), [Some(3)]);
2936        assert_eq!(snapshot.buffer_rows(5).collect::<Vec<_>>(), []);
2937
2938        assert_eq!(
2939            boundaries_in_range(Point::new(0, 0)..Point::new(4, 2), &snapshot),
2940            &[
2941                (0, "bbbb\nccccc".to_string(), true),
2942                (2, "ddd\neeee".to_string(), false),
2943                (4, "jj".to_string(), true),
2944            ]
2945        );
2946        assert_eq!(
2947            boundaries_in_range(Point::new(0, 0)..Point::new(2, 0), &snapshot),
2948            &[(0, "bbbb\nccccc".to_string(), true)]
2949        );
2950        assert_eq!(
2951            boundaries_in_range(Point::new(1, 0)..Point::new(1, 5), &snapshot),
2952            &[]
2953        );
2954        assert_eq!(
2955            boundaries_in_range(Point::new(1, 0)..Point::new(2, 0), &snapshot),
2956            &[]
2957        );
2958        assert_eq!(
2959            boundaries_in_range(Point::new(1, 0)..Point::new(4, 0), &snapshot),
2960            &[(2, "ddd\neeee".to_string(), false)]
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(2, 0)..Point::new(3, 0), &snapshot),
2968            &[(2, "ddd\neeee".to_string(), false)]
2969        );
2970        assert_eq!(
2971            boundaries_in_range(Point::new(4, 0)..Point::new(4, 2), &snapshot),
2972            &[(4, "jj".to_string(), true)]
2973        );
2974        assert_eq!(
2975            boundaries_in_range(Point::new(4, 2)..Point::new(4, 2), &snapshot),
2976            &[]
2977        );
2978
2979        buffer_1.update(cx, |buffer, cx| {
2980            buffer.edit(
2981                [
2982                    Point::new(0, 0)..Point::new(0, 0),
2983                    Point::new(2, 1)..Point::new(2, 3),
2984                ],
2985                "\n",
2986                cx,
2987            );
2988        });
2989
2990        let snapshot = multibuffer.read(cx).snapshot(cx);
2991        assert_eq!(
2992            snapshot.text(),
2993            concat!(
2994                "bbbb\n", // Preserve newlines
2995                "c\n",    //
2996                "cc\n",   //
2997                "ddd\n",  //
2998                "eeee\n", //
2999                "jj"      //
3000            )
3001        );
3002
3003        assert_eq!(
3004            subscription.consume().into_inner(),
3005            [Edit {
3006                old: 6..8,
3007                new: 6..7
3008            }]
3009        );
3010
3011        let snapshot = multibuffer.read(cx).snapshot(cx);
3012        assert_eq!(
3013            snapshot.clip_point(Point::new(0, 5), Bias::Left),
3014            Point::new(0, 4)
3015        );
3016        assert_eq!(
3017            snapshot.clip_point(Point::new(0, 5), Bias::Right),
3018            Point::new(0, 4)
3019        );
3020        assert_eq!(
3021            snapshot.clip_point(Point::new(5, 1), Bias::Right),
3022            Point::new(5, 1)
3023        );
3024        assert_eq!(
3025            snapshot.clip_point(Point::new(5, 2), Bias::Right),
3026            Point::new(5, 2)
3027        );
3028        assert_eq!(
3029            snapshot.clip_point(Point::new(5, 3), Bias::Right),
3030            Point::new(5, 2)
3031        );
3032
3033        let snapshot = multibuffer.update(cx, |multibuffer, cx| {
3034            let buffer_2_excerpt_id = multibuffer.excerpt_ids_for_buffer(&buffer_2)[0].clone();
3035            multibuffer.remove_excerpts(&[buffer_2_excerpt_id], cx);
3036            multibuffer.snapshot(cx)
3037        });
3038
3039        assert_eq!(
3040            snapshot.text(),
3041            concat!(
3042                "bbbb\n", // Preserve newlines
3043                "c\n",    //
3044                "cc\n",   //
3045                "ddd\n",  //
3046                "eeee",   //
3047            )
3048        );
3049
3050        fn boundaries_in_range(
3051            range: Range<Point>,
3052            snapshot: &MultiBufferSnapshot,
3053        ) -> Vec<(u32, String, bool)> {
3054            snapshot
3055                .excerpt_boundaries_in_range(range)
3056                .map(|boundary| {
3057                    (
3058                        boundary.row,
3059                        boundary
3060                            .buffer
3061                            .text_for_range(boundary.range)
3062                            .collect::<String>(),
3063                        boundary.starts_new_buffer,
3064                    )
3065                })
3066                .collect::<Vec<_>>()
3067        }
3068    }
3069
3070    #[gpui::test]
3071    fn test_excerpts_with_context_lines(cx: &mut MutableAppContext) {
3072        let buffer = cx.add_model(|cx| Buffer::new(0, sample_text(20, 3, 'a'), cx));
3073        let multibuffer = cx.add_model(|_| MultiBuffer::new(0));
3074        let anchor_ranges = multibuffer.update(cx, |multibuffer, cx| {
3075            multibuffer.push_excerpts_with_context_lines(
3076                buffer.clone(),
3077                vec![
3078                    Point::new(3, 2)..Point::new(4, 2),
3079                    Point::new(7, 1)..Point::new(7, 3),
3080                    Point::new(15, 0)..Point::new(15, 0),
3081                ],
3082                2,
3083                cx,
3084            )
3085        });
3086
3087        let snapshot = multibuffer.read(cx).snapshot(cx);
3088        assert_eq!(
3089            snapshot.text(),
3090            "bbb\nccc\nddd\neee\nfff\nggg\nhhh\niii\njjj\n\nnnn\nooo\nppp\nqqq\nrrr\n"
3091        );
3092
3093        assert_eq!(
3094            anchor_ranges
3095                .iter()
3096                .map(|range| range.to_point(&snapshot))
3097                .collect::<Vec<_>>(),
3098            vec![
3099                Point::new(2, 2)..Point::new(3, 2),
3100                Point::new(6, 1)..Point::new(6, 3),
3101                Point::new(12, 0)..Point::new(12, 0)
3102            ]
3103        );
3104    }
3105
3106    #[gpui::test]
3107    fn test_empty_excerpt_buffer(cx: &mut MutableAppContext) {
3108        let multibuffer = cx.add_model(|_| MultiBuffer::new(0));
3109
3110        let snapshot = multibuffer.read(cx).snapshot(cx);
3111        assert_eq!(snapshot.text(), "");
3112        assert_eq!(snapshot.buffer_rows(0).collect::<Vec<_>>(), &[Some(0)]);
3113        assert_eq!(snapshot.buffer_rows(1).collect::<Vec<_>>(), &[]);
3114    }
3115
3116    #[gpui::test]
3117    fn test_singleton_multibuffer_anchors(cx: &mut MutableAppContext) {
3118        let buffer = cx.add_model(|cx| Buffer::new(0, "abcd", cx));
3119        let multibuffer = cx.add_model(|cx| MultiBuffer::singleton(buffer.clone(), cx));
3120        let old_snapshot = multibuffer.read(cx).snapshot(cx);
3121        buffer.update(cx, |buffer, cx| {
3122            buffer.edit([0..0], "X", cx);
3123            buffer.edit([5..5], "Y", cx);
3124        });
3125        let new_snapshot = multibuffer.read(cx).snapshot(cx);
3126
3127        assert_eq!(old_snapshot.text(), "abcd");
3128        assert_eq!(new_snapshot.text(), "XabcdY");
3129
3130        assert_eq!(old_snapshot.anchor_before(0).to_offset(&new_snapshot), 0);
3131        assert_eq!(old_snapshot.anchor_after(0).to_offset(&new_snapshot), 1);
3132        assert_eq!(old_snapshot.anchor_before(4).to_offset(&new_snapshot), 5);
3133        assert_eq!(old_snapshot.anchor_after(4).to_offset(&new_snapshot), 6);
3134    }
3135
3136    #[gpui::test]
3137    fn test_multibuffer_anchors(cx: &mut MutableAppContext) {
3138        let buffer_1 = cx.add_model(|cx| Buffer::new(0, "abcd", cx));
3139        let buffer_2 = cx.add_model(|cx| Buffer::new(0, "efghi", cx));
3140        let multibuffer = cx.add_model(|cx| {
3141            let mut multibuffer = MultiBuffer::new(0);
3142            multibuffer.push_excerpts(buffer_1.clone(), [0..4], cx);
3143            multibuffer.push_excerpts(buffer_2.clone(), [0..5], cx);
3144            multibuffer
3145        });
3146        let old_snapshot = multibuffer.read(cx).snapshot(cx);
3147
3148        assert_eq!(old_snapshot.anchor_before(0).to_offset(&old_snapshot), 0);
3149        assert_eq!(old_snapshot.anchor_after(0).to_offset(&old_snapshot), 0);
3150        assert_eq!(Anchor::min().to_offset(&old_snapshot), 0);
3151        assert_eq!(Anchor::min().to_offset(&old_snapshot), 0);
3152        assert_eq!(Anchor::max().to_offset(&old_snapshot), 10);
3153        assert_eq!(Anchor::max().to_offset(&old_snapshot), 10);
3154
3155        buffer_1.update(cx, |buffer, cx| {
3156            buffer.edit([0..0], "W", cx);
3157            buffer.edit([5..5], "X", cx);
3158        });
3159        buffer_2.update(cx, |buffer, cx| {
3160            buffer.edit([0..0], "Y", cx);
3161            buffer.edit([6..0], "Z", cx);
3162        });
3163        let new_snapshot = multibuffer.read(cx).snapshot(cx);
3164
3165        assert_eq!(old_snapshot.text(), "abcd\nefghi");
3166        assert_eq!(new_snapshot.text(), "WabcdX\nYefghiZ");
3167
3168        assert_eq!(old_snapshot.anchor_before(0).to_offset(&new_snapshot), 0);
3169        assert_eq!(old_snapshot.anchor_after(0).to_offset(&new_snapshot), 1);
3170        assert_eq!(old_snapshot.anchor_before(1).to_offset(&new_snapshot), 2);
3171        assert_eq!(old_snapshot.anchor_after(1).to_offset(&new_snapshot), 2);
3172        assert_eq!(old_snapshot.anchor_before(2).to_offset(&new_snapshot), 3);
3173        assert_eq!(old_snapshot.anchor_after(2).to_offset(&new_snapshot), 3);
3174        assert_eq!(old_snapshot.anchor_before(5).to_offset(&new_snapshot), 7);
3175        assert_eq!(old_snapshot.anchor_after(5).to_offset(&new_snapshot), 8);
3176        assert_eq!(old_snapshot.anchor_before(10).to_offset(&new_snapshot), 13);
3177        assert_eq!(old_snapshot.anchor_after(10).to_offset(&new_snapshot), 14);
3178    }
3179
3180    #[gpui::test]
3181    fn test_multibuffer_resolving_anchors_after_replacing_their_excerpts(
3182        cx: &mut MutableAppContext,
3183    ) {
3184        let buffer_1 = cx.add_model(|cx| Buffer::new(0, "abcd", cx));
3185        let buffer_2 = cx.add_model(|cx| Buffer::new(0, "ABCDEFGHIJKLMNOP", cx));
3186        let multibuffer = cx.add_model(|_| MultiBuffer::new(0));
3187
3188        // Create an insertion id in buffer 1 that doesn't exist in buffer 2.
3189        // Add an excerpt from buffer 1 that spans this new insertion.
3190        buffer_1.update(cx, |buffer, cx| buffer.edit([4..4], "123", cx));
3191        let excerpt_id_1 = multibuffer.update(cx, |multibuffer, cx| {
3192            multibuffer
3193                .push_excerpts(buffer_1.clone(), [0..7], cx)
3194                .pop()
3195                .unwrap()
3196        });
3197
3198        let snapshot_1 = multibuffer.read(cx).snapshot(cx);
3199        assert_eq!(snapshot_1.text(), "abcd123");
3200
3201        // Replace the buffer 1 excerpt with new excerpts from buffer 2.
3202        let (excerpt_id_2, excerpt_id_3) = multibuffer.update(cx, |multibuffer, cx| {
3203            multibuffer.remove_excerpts([&excerpt_id_1], cx);
3204            let mut ids = multibuffer
3205                .push_excerpts(buffer_2.clone(), [0..4, 6..10, 12..16], cx)
3206                .into_iter();
3207            (ids.next().unwrap(), ids.next().unwrap())
3208        });
3209        let snapshot_2 = multibuffer.read(cx).snapshot(cx);
3210        assert_eq!(snapshot_2.text(), "ABCD\nGHIJ\nMNOP");
3211
3212        // The old excerpt id has been reused.
3213        assert_eq!(excerpt_id_2, excerpt_id_1);
3214
3215        // Resolve some anchors from the previous snapshot in the new snapshot.
3216        // Although there is still an excerpt with the same id, it is for
3217        // a different buffer, so we don't attempt to resolve the old text
3218        // anchor in the new buffer.
3219        assert_eq!(
3220            snapshot_2.summary_for_anchor::<usize>(&snapshot_1.anchor_before(2)),
3221            0
3222        );
3223        assert_eq!(
3224            snapshot_2.summaries_for_anchors::<usize, _>(&[
3225                snapshot_1.anchor_before(2),
3226                snapshot_1.anchor_after(3)
3227            ]),
3228            vec![0, 0]
3229        );
3230        let refresh =
3231            snapshot_2.refresh_anchors(&[snapshot_1.anchor_before(2), snapshot_1.anchor_after(3)]);
3232        assert_eq!(
3233            refresh,
3234            &[
3235                (0, snapshot_2.anchor_before(0), false),
3236                (1, snapshot_2.anchor_after(0), false),
3237            ]
3238        );
3239
3240        // Replace the middle excerpt with a smaller excerpt in buffer 2,
3241        // that intersects the old excerpt.
3242        let excerpt_id_5 = multibuffer.update(cx, |multibuffer, cx| {
3243            multibuffer.remove_excerpts([&excerpt_id_3], cx);
3244            multibuffer
3245                .insert_excerpts_after(&excerpt_id_3, buffer_2.clone(), [5..8], cx)
3246                .pop()
3247                .unwrap()
3248        });
3249
3250        let snapshot_3 = multibuffer.read(cx).snapshot(cx);
3251        assert_eq!(snapshot_3.text(), "ABCD\nFGH\nMNOP");
3252        assert_ne!(excerpt_id_5, excerpt_id_3);
3253
3254        // Resolve some anchors from the previous snapshot in the new snapshot.
3255        // The anchor in the middle excerpt snaps to the beginning of the
3256        // excerpt, since it is not
3257        let anchors = [
3258            snapshot_2.anchor_before(0),
3259            snapshot_2.anchor_after(2),
3260            snapshot_2.anchor_after(6),
3261            snapshot_2.anchor_after(14),
3262        ];
3263        assert_eq!(
3264            snapshot_3.summaries_for_anchors::<usize, _>(&anchors),
3265            &[0, 2, 9, 13]
3266        );
3267
3268        let new_anchors = snapshot_3.refresh_anchors(&anchors);
3269        assert_eq!(
3270            new_anchors.iter().map(|a| (a.0, a.2)).collect::<Vec<_>>(),
3271            &[(0, true), (1, true), (2, true), (3, true)]
3272        );
3273        assert_eq!(
3274            snapshot_3.summaries_for_anchors::<usize, _>(new_anchors.iter().map(|a| &a.1)),
3275            &[0, 2, 7, 13]
3276        );
3277    }
3278
3279    #[gpui::test(iterations = 100)]
3280    fn test_random_multibuffer(cx: &mut MutableAppContext, mut rng: StdRng) {
3281        let operations = env::var("OPERATIONS")
3282            .map(|i| i.parse().expect("invalid `OPERATIONS` variable"))
3283            .unwrap_or(10);
3284
3285        let mut buffers: Vec<ModelHandle<Buffer>> = Vec::new();
3286        let multibuffer = cx.add_model(|_| MultiBuffer::new(0));
3287        let mut excerpt_ids = Vec::new();
3288        let mut expected_excerpts = Vec::<(ModelHandle<Buffer>, Range<text::Anchor>)>::new();
3289        let mut anchors = Vec::new();
3290        let mut old_versions = Vec::new();
3291
3292        for _ in 0..operations {
3293            match rng.gen_range(0..100) {
3294                0..=19 if !buffers.is_empty() => {
3295                    let buffer = buffers.choose(&mut rng).unwrap();
3296                    buffer.update(cx, |buf, cx| buf.randomly_edit(&mut rng, 5, cx));
3297                }
3298                20..=29 if !expected_excerpts.is_empty() => {
3299                    let mut ids_to_remove = vec![];
3300                    for _ in 0..rng.gen_range(1..=3) {
3301                        if expected_excerpts.is_empty() {
3302                            break;
3303                        }
3304
3305                        let ix = rng.gen_range(0..expected_excerpts.len());
3306                        ids_to_remove.push(excerpt_ids.remove(ix));
3307                        let (buffer, range) = expected_excerpts.remove(ix);
3308                        let buffer = buffer.read(cx);
3309                        log::info!(
3310                            "Removing excerpt {}: {:?}",
3311                            ix,
3312                            buffer
3313                                .text_for_range(range.to_offset(&buffer))
3314                                .collect::<String>(),
3315                        );
3316                    }
3317                    ids_to_remove.sort_unstable();
3318                    multibuffer.update(cx, |multibuffer, cx| {
3319                        multibuffer.remove_excerpts(&ids_to_remove, cx)
3320                    });
3321                }
3322                30..=39 if !expected_excerpts.is_empty() => {
3323                    let multibuffer = multibuffer.read(cx).read(cx);
3324                    let offset =
3325                        multibuffer.clip_offset(rng.gen_range(0..=multibuffer.len()), Bias::Left);
3326                    let bias = if rng.gen() { Bias::Left } else { Bias::Right };
3327                    log::info!("Creating anchor at {} with bias {:?}", offset, bias);
3328                    anchors.push(multibuffer.anchor_at(offset, bias));
3329                    anchors.sort_by(|a, b| a.cmp(&b, &multibuffer).unwrap());
3330                }
3331                40..=44 if !anchors.is_empty() => {
3332                    let multibuffer = multibuffer.read(cx).read(cx);
3333
3334                    anchors = multibuffer
3335                        .refresh_anchors(&anchors)
3336                        .into_iter()
3337                        .map(|a| a.1)
3338                        .collect();
3339
3340                    // Ensure the newly-refreshed anchors point to a valid excerpt and don't
3341                    // overshoot its boundaries.
3342                    let mut cursor = multibuffer.excerpts.cursor::<Option<&ExcerptId>>();
3343                    for anchor in &anchors {
3344                        if anchor.excerpt_id == ExcerptId::min()
3345                            || anchor.excerpt_id == ExcerptId::max()
3346                        {
3347                            continue;
3348                        }
3349
3350                        cursor.seek_forward(&Some(&anchor.excerpt_id), Bias::Left, &());
3351                        let excerpt = cursor.item().unwrap();
3352                        assert_eq!(excerpt.id, anchor.excerpt_id);
3353                        assert!(excerpt.contains(anchor));
3354                    }
3355                }
3356                _ => {
3357                    let buffer_handle = if buffers.is_empty() || rng.gen_bool(0.4) {
3358                        let base_text = RandomCharIter::new(&mut rng).take(10).collect::<String>();
3359                        buffers.push(cx.add_model(|cx| Buffer::new(0, base_text, cx)));
3360                        buffers.last().unwrap()
3361                    } else {
3362                        buffers.choose(&mut rng).unwrap()
3363                    };
3364
3365                    let buffer = buffer_handle.read(cx);
3366                    let end_ix = buffer.clip_offset(rng.gen_range(0..=buffer.len()), Bias::Right);
3367                    let start_ix = buffer.clip_offset(rng.gen_range(0..=end_ix), Bias::Left);
3368                    let anchor_range = buffer.anchor_before(start_ix)..buffer.anchor_after(end_ix);
3369                    let prev_excerpt_ix = rng.gen_range(0..=expected_excerpts.len());
3370                    let prev_excerpt_id = excerpt_ids
3371                        .get(prev_excerpt_ix)
3372                        .cloned()
3373                        .unwrap_or(ExcerptId::max());
3374                    let excerpt_ix = (prev_excerpt_ix + 1).min(expected_excerpts.len());
3375
3376                    log::info!(
3377                        "Inserting excerpt at {} of {} for buffer {}: {:?}[{:?}] = {:?}",
3378                        excerpt_ix,
3379                        expected_excerpts.len(),
3380                        buffer_handle.id(),
3381                        buffer.text(),
3382                        start_ix..end_ix,
3383                        &buffer.text()[start_ix..end_ix]
3384                    );
3385
3386                    let excerpt_id = multibuffer.update(cx, |multibuffer, cx| {
3387                        multibuffer
3388                            .insert_excerpts_after(
3389                                &prev_excerpt_id,
3390                                buffer_handle.clone(),
3391                                [start_ix..end_ix],
3392                                cx,
3393                            )
3394                            .pop()
3395                            .unwrap()
3396                    });
3397
3398                    excerpt_ids.insert(excerpt_ix, excerpt_id);
3399                    expected_excerpts.insert(excerpt_ix, (buffer_handle.clone(), anchor_range));
3400                }
3401            }
3402
3403            if rng.gen_bool(0.3) {
3404                multibuffer.update(cx, |multibuffer, cx| {
3405                    old_versions.push((multibuffer.snapshot(cx), multibuffer.subscribe()));
3406                })
3407            }
3408
3409            let snapshot = multibuffer.read(cx).snapshot(cx);
3410
3411            let mut excerpt_starts = Vec::new();
3412            let mut expected_text = String::new();
3413            let mut expected_buffer_rows = Vec::new();
3414            for (buffer, range) in &expected_excerpts {
3415                let buffer = buffer.read(cx);
3416                let buffer_range = range.to_offset(buffer);
3417
3418                excerpt_starts.push(TextSummary::from(expected_text.as_str()));
3419                expected_text.extend(buffer.text_for_range(buffer_range.clone()));
3420                expected_text.push('\n');
3421
3422                let buffer_row_range = buffer.offset_to_point(buffer_range.start).row
3423                    ..=buffer.offset_to_point(buffer_range.end).row;
3424                for row in buffer_row_range {
3425                    expected_buffer_rows.push(Some(row));
3426                }
3427            }
3428            // Remove final trailing newline.
3429            if !expected_excerpts.is_empty() {
3430                expected_text.pop();
3431            }
3432
3433            // Always report one buffer row
3434            if expected_buffer_rows.is_empty() {
3435                expected_buffer_rows.push(Some(0));
3436            }
3437
3438            assert_eq!(snapshot.text(), expected_text);
3439            log::info!("MultiBuffer text: {:?}", expected_text);
3440
3441            assert_eq!(
3442                snapshot.buffer_rows(0).collect::<Vec<_>>(),
3443                expected_buffer_rows,
3444            );
3445
3446            for _ in 0..5 {
3447                let start_row = rng.gen_range(0..=expected_buffer_rows.len());
3448                assert_eq!(
3449                    snapshot.buffer_rows(start_row as u32).collect::<Vec<_>>(),
3450                    &expected_buffer_rows[start_row..],
3451                    "buffer_rows({})",
3452                    start_row
3453                );
3454            }
3455
3456            assert_eq!(
3457                snapshot.max_buffer_row(),
3458                expected_buffer_rows
3459                    .into_iter()
3460                    .filter_map(|r| r)
3461                    .max()
3462                    .unwrap()
3463            );
3464
3465            let mut excerpt_starts = excerpt_starts.into_iter();
3466            for (buffer, range) in &expected_excerpts {
3467                let buffer_id = buffer.id();
3468                let buffer = buffer.read(cx);
3469                let buffer_range = range.to_offset(buffer);
3470                let buffer_start_point = buffer.offset_to_point(buffer_range.start);
3471                let buffer_start_point_utf16 =
3472                    buffer.text_summary_for_range::<PointUtf16, _>(0..buffer_range.start);
3473
3474                let excerpt_start = excerpt_starts.next().unwrap();
3475                let mut offset = excerpt_start.bytes;
3476                let mut buffer_offset = buffer_range.start;
3477                let mut point = excerpt_start.lines;
3478                let mut buffer_point = buffer_start_point;
3479                let mut point_utf16 = excerpt_start.lines_utf16;
3480                let mut buffer_point_utf16 = buffer_start_point_utf16;
3481                for ch in buffer
3482                    .snapshot()
3483                    .chunks(buffer_range.clone(), false)
3484                    .flat_map(|c| c.text.chars())
3485                {
3486                    for _ in 0..ch.len_utf8() {
3487                        let left_offset = snapshot.clip_offset(offset, Bias::Left);
3488                        let right_offset = snapshot.clip_offset(offset, Bias::Right);
3489                        let buffer_left_offset = buffer.clip_offset(buffer_offset, Bias::Left);
3490                        let buffer_right_offset = buffer.clip_offset(buffer_offset, Bias::Right);
3491                        assert_eq!(
3492                            left_offset,
3493                            excerpt_start.bytes + (buffer_left_offset - buffer_range.start),
3494                            "clip_offset({:?}, Left). buffer: {:?}, buffer offset: {:?}",
3495                            offset,
3496                            buffer_id,
3497                            buffer_offset,
3498                        );
3499                        assert_eq!(
3500                            right_offset,
3501                            excerpt_start.bytes + (buffer_right_offset - buffer_range.start),
3502                            "clip_offset({:?}, Right). buffer: {:?}, buffer offset: {:?}",
3503                            offset,
3504                            buffer_id,
3505                            buffer_offset,
3506                        );
3507
3508                        let left_point = snapshot.clip_point(point, Bias::Left);
3509                        let right_point = snapshot.clip_point(point, Bias::Right);
3510                        let buffer_left_point = buffer.clip_point(buffer_point, Bias::Left);
3511                        let buffer_right_point = buffer.clip_point(buffer_point, Bias::Right);
3512                        assert_eq!(
3513                            left_point,
3514                            excerpt_start.lines + (buffer_left_point - buffer_start_point),
3515                            "clip_point({:?}, Left). buffer: {:?}, buffer point: {:?}",
3516                            point,
3517                            buffer_id,
3518                            buffer_point,
3519                        );
3520                        assert_eq!(
3521                            right_point,
3522                            excerpt_start.lines + (buffer_right_point - buffer_start_point),
3523                            "clip_point({:?}, Right). buffer: {:?}, buffer point: {:?}",
3524                            point,
3525                            buffer_id,
3526                            buffer_point,
3527                        );
3528
3529                        assert_eq!(
3530                            snapshot.point_to_offset(left_point),
3531                            left_offset,
3532                            "point_to_offset({:?})",
3533                            left_point,
3534                        );
3535                        assert_eq!(
3536                            snapshot.offset_to_point(left_offset),
3537                            left_point,
3538                            "offset_to_point({:?})",
3539                            left_offset,
3540                        );
3541
3542                        offset += 1;
3543                        buffer_offset += 1;
3544                        if ch == '\n' {
3545                            point += Point::new(1, 0);
3546                            buffer_point += Point::new(1, 0);
3547                        } else {
3548                            point += Point::new(0, 1);
3549                            buffer_point += Point::new(0, 1);
3550                        }
3551                    }
3552
3553                    for _ in 0..ch.len_utf16() {
3554                        let left_point_utf16 = snapshot.clip_point_utf16(point_utf16, Bias::Left);
3555                        let right_point_utf16 = snapshot.clip_point_utf16(point_utf16, Bias::Right);
3556                        let buffer_left_point_utf16 =
3557                            buffer.clip_point_utf16(buffer_point_utf16, Bias::Left);
3558                        let buffer_right_point_utf16 =
3559                            buffer.clip_point_utf16(buffer_point_utf16, Bias::Right);
3560                        assert_eq!(
3561                            left_point_utf16,
3562                            excerpt_start.lines_utf16
3563                                + (buffer_left_point_utf16 - buffer_start_point_utf16),
3564                            "clip_point_utf16({:?}, Left). buffer: {:?}, buffer point_utf16: {:?}",
3565                            point_utf16,
3566                            buffer_id,
3567                            buffer_point_utf16,
3568                        );
3569                        assert_eq!(
3570                            right_point_utf16,
3571                            excerpt_start.lines_utf16
3572                                + (buffer_right_point_utf16 - buffer_start_point_utf16),
3573                            "clip_point_utf16({:?}, Right). buffer: {:?}, buffer point_utf16: {:?}",
3574                            point_utf16,
3575                            buffer_id,
3576                            buffer_point_utf16,
3577                        );
3578
3579                        if ch == '\n' {
3580                            point_utf16 += PointUtf16::new(1, 0);
3581                            buffer_point_utf16 += PointUtf16::new(1, 0);
3582                        } else {
3583                            point_utf16 += PointUtf16::new(0, 1);
3584                            buffer_point_utf16 += PointUtf16::new(0, 1);
3585                        }
3586                    }
3587                }
3588            }
3589
3590            for (row, line) in expected_text.split('\n').enumerate() {
3591                assert_eq!(
3592                    snapshot.line_len(row as u32),
3593                    line.len() as u32,
3594                    "line_len({}).",
3595                    row
3596                );
3597            }
3598
3599            let text_rope = Rope::from(expected_text.as_str());
3600            for _ in 0..10 {
3601                let end_ix = text_rope.clip_offset(rng.gen_range(0..=text_rope.len()), Bias::Right);
3602                let start_ix = text_rope.clip_offset(rng.gen_range(0..=end_ix), Bias::Left);
3603
3604                let text_for_range = snapshot
3605                    .text_for_range(start_ix..end_ix)
3606                    .collect::<String>();
3607                assert_eq!(
3608                    text_for_range,
3609                    &expected_text[start_ix..end_ix],
3610                    "incorrect text for range {:?}",
3611                    start_ix..end_ix
3612                );
3613
3614                let excerpted_buffer_ranges = multibuffer
3615                    .read(cx)
3616                    .range_to_buffer_ranges(start_ix..end_ix, cx);
3617                let excerpted_buffers_text = excerpted_buffer_ranges
3618                    .into_iter()
3619                    .map(|(buffer, buffer_range)| {
3620                        buffer
3621                            .read(cx)
3622                            .text_for_range(buffer_range)
3623                            .collect::<String>()
3624                    })
3625                    .collect::<Vec<_>>()
3626                    .join("\n");
3627                assert_eq!(excerpted_buffers_text, text_for_range);
3628
3629                let expected_summary = TextSummary::from(&expected_text[start_ix..end_ix]);
3630                assert_eq!(
3631                    snapshot.text_summary_for_range::<TextSummary, _>(start_ix..end_ix),
3632                    expected_summary,
3633                    "incorrect summary for range {:?}",
3634                    start_ix..end_ix
3635                );
3636            }
3637
3638            // Anchor resolution
3639            for (anchor, resolved_offset) in anchors
3640                .iter()
3641                .zip(snapshot.summaries_for_anchors::<usize, _>(&anchors))
3642            {
3643                assert!(resolved_offset <= snapshot.len());
3644                assert_eq!(
3645                    snapshot.summary_for_anchor::<usize>(anchor),
3646                    resolved_offset
3647                );
3648            }
3649
3650            for _ in 0..10 {
3651                let end_ix = text_rope.clip_offset(rng.gen_range(0..=text_rope.len()), Bias::Right);
3652                assert_eq!(
3653                    snapshot.reversed_chars_at(end_ix).collect::<String>(),
3654                    expected_text[..end_ix].chars().rev().collect::<String>(),
3655                );
3656            }
3657
3658            for _ in 0..10 {
3659                let end_ix = rng.gen_range(0..=text_rope.len());
3660                let start_ix = rng.gen_range(0..=end_ix);
3661                assert_eq!(
3662                    snapshot
3663                        .bytes_in_range(start_ix..end_ix)
3664                        .flatten()
3665                        .copied()
3666                        .collect::<Vec<_>>(),
3667                    expected_text.as_bytes()[start_ix..end_ix].to_vec(),
3668                    "bytes_in_range({:?})",
3669                    start_ix..end_ix,
3670                );
3671            }
3672        }
3673
3674        let snapshot = multibuffer.read(cx).snapshot(cx);
3675        for (old_snapshot, subscription) in old_versions {
3676            let edits = subscription.consume().into_inner();
3677
3678            log::info!(
3679                "applying subscription edits to old text: {:?}: {:?}",
3680                old_snapshot.text(),
3681                edits,
3682            );
3683
3684            let mut text = old_snapshot.text();
3685            for edit in edits {
3686                let new_text: String = snapshot.text_for_range(edit.new.clone()).collect();
3687                text.replace_range(edit.new.start..edit.new.start + edit.old.len(), &new_text);
3688            }
3689            assert_eq!(text.to_string(), snapshot.text());
3690        }
3691    }
3692
3693    #[gpui::test]
3694    fn test_history(cx: &mut MutableAppContext) {
3695        let buffer_1 = cx.add_model(|cx| Buffer::new(0, "1234", cx));
3696        let buffer_2 = cx.add_model(|cx| Buffer::new(0, "5678", cx));
3697        let multibuffer = cx.add_model(|_| MultiBuffer::new(0));
3698        let group_interval = multibuffer.read(cx).history.group_interval;
3699        multibuffer.update(cx, |multibuffer, cx| {
3700            multibuffer.push_excerpts(buffer_1.clone(), [0..buffer_1.read(cx).len()], cx);
3701            multibuffer.push_excerpts(buffer_2.clone(), [0..buffer_2.read(cx).len()], cx);
3702        });
3703
3704        let mut now = Instant::now();
3705
3706        multibuffer.update(cx, |multibuffer, cx| {
3707            multibuffer.start_transaction_at(now, cx);
3708            multibuffer.edit(
3709                [
3710                    Point::new(0, 0)..Point::new(0, 0),
3711                    Point::new(1, 0)..Point::new(1, 0),
3712                ],
3713                "A",
3714                cx,
3715            );
3716            multibuffer.edit(
3717                [
3718                    Point::new(0, 1)..Point::new(0, 1),
3719                    Point::new(1, 1)..Point::new(1, 1),
3720                ],
3721                "B",
3722                cx,
3723            );
3724            multibuffer.end_transaction_at(now, cx);
3725            assert_eq!(multibuffer.read(cx).text(), "AB1234\nAB5678");
3726
3727            // Edit buffer 1 through the multibuffer
3728            now += 2 * group_interval;
3729            multibuffer.start_transaction_at(now, cx);
3730            multibuffer.edit([2..2], "C", cx);
3731            multibuffer.end_transaction_at(now, cx);
3732            assert_eq!(multibuffer.read(cx).text(), "ABC1234\nAB5678");
3733
3734            // Edit buffer 1 independently
3735            buffer_1.update(cx, |buffer_1, cx| {
3736                buffer_1.start_transaction_at(now);
3737                buffer_1.edit([3..3], "D", cx);
3738                buffer_1.end_transaction_at(now, cx);
3739
3740                now += 2 * group_interval;
3741                buffer_1.start_transaction_at(now);
3742                buffer_1.edit([4..4], "E", cx);
3743                buffer_1.end_transaction_at(now, cx);
3744            });
3745            assert_eq!(multibuffer.read(cx).text(), "ABCDE1234\nAB5678");
3746
3747            // An undo in the multibuffer undoes the multibuffer transaction
3748            // and also any individual buffer edits that have occured since
3749            // that transaction.
3750            multibuffer.undo(cx);
3751            assert_eq!(multibuffer.read(cx).text(), "AB1234\nAB5678");
3752
3753            multibuffer.undo(cx);
3754            assert_eq!(multibuffer.read(cx).text(), "1234\n5678");
3755
3756            multibuffer.redo(cx);
3757            assert_eq!(multibuffer.read(cx).text(), "AB1234\nAB5678");
3758
3759            multibuffer.redo(cx);
3760            assert_eq!(multibuffer.read(cx).text(), "ABCDE1234\nAB5678");
3761
3762            // Undo buffer 2 independently.
3763            buffer_2.update(cx, |buffer_2, cx| buffer_2.undo(cx));
3764            assert_eq!(multibuffer.read(cx).text(), "ABCDE1234\n5678");
3765
3766            // An undo in the multibuffer undoes the components of the
3767            // the last multibuffer transaction that are not already undone.
3768            multibuffer.undo(cx);
3769            assert_eq!(multibuffer.read(cx).text(), "AB1234\n5678");
3770
3771            multibuffer.undo(cx);
3772            assert_eq!(multibuffer.read(cx).text(), "1234\n5678");
3773
3774            multibuffer.redo(cx);
3775            assert_eq!(multibuffer.read(cx).text(), "AB1234\nAB5678");
3776
3777            buffer_1.update(cx, |buffer_1, cx| buffer_1.redo(cx));
3778            assert_eq!(multibuffer.read(cx).text(), "ABCD1234\nAB5678");
3779
3780            multibuffer.undo(cx);
3781            assert_eq!(multibuffer.read(cx).text(), "1234\n5678");
3782        });
3783    }
3784}