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