multi_buffer.rs

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