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