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