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