multi_buffer.rs

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