multi_buffer.rs

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