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