multi_buffer.rs

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