multi_buffer.rs

   1mod anchor;
   2
   3pub use anchor::{Anchor, AnchorRangeExt};
   4use anyhow::{anyhow, Result};
   5use clock::ReplicaId;
   6use collections::{BTreeMap, Bound, HashMap, HashSet};
   7use futures::{channel::mpsc, SinkExt};
   8use git::diff::DiffHunk;
   9use gpui::{AppContext, Entity, ModelContext, ModelHandle, Task};
  10pub use language::Completion;
  11use language::{
  12    char_kind,
  13    language_settings::{language_settings, LanguageSettings},
  14    AutoindentMode, Buffer, BufferChunks, BufferSnapshot, CharKind, Chunk, CursorShape,
  15    DiagnosticEntry, File, IndentSize, Language, LanguageScope, OffsetRangeExt, OffsetUtf16,
  16    Outline, OutlineItem, Point, PointUtf16, Selection, TextDimension, ToOffset as _,
  17    ToOffsetUtf16 as _, ToPoint as _, ToPointUtf16 as _, TransactionId, Unclipped,
  18};
  19use std::{
  20    borrow::Cow,
  21    cell::{Ref, RefCell},
  22    cmp, fmt,
  23    future::Future,
  24    io,
  25    iter::{self, FromIterator},
  26    mem,
  27    ops::{Range, RangeBounds, Sub},
  28    str,
  29    sync::Arc,
  30    time::{Duration, Instant},
  31};
  32use sum_tree::{Bias, Cursor, SumTree};
  33use text::{
  34    locator::Locator,
  35    subscription::{Subscription, Topic},
  36    Edit, TextSummary,
  37};
  38use theme::SyntaxTheme;
  39use util::post_inc;
  40
  41const NEWLINES: &[u8] = &[b'\n'; u8::MAX as usize];
  42
  43#[derive(Debug, Default, Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)]
  44pub struct ExcerptId(usize);
  45
  46pub struct MultiBuffer {
  47    snapshot: RefCell<MultiBufferSnapshot>,
  48    buffers: RefCell<HashMap<u64, BufferState>>,
  49    next_excerpt_id: usize,
  50    subscriptions: Topic,
  51    singleton: bool,
  52    replica_id: ReplicaId,
  53    history: History,
  54    title: Option<String>,
  55}
  56
  57#[derive(Clone, Debug, PartialEq, Eq)]
  58pub enum Event {
  59    ExcerptsAdded {
  60        buffer: ModelHandle<Buffer>,
  61        predecessor: ExcerptId,
  62        excerpts: Vec<(ExcerptId, ExcerptRange<language::Anchor>)>,
  63    },
  64    ExcerptsRemoved {
  65        ids: Vec<ExcerptId>,
  66    },
  67    Edited,
  68    Reloaded,
  69    LanguageChanged,
  70    Reparsed,
  71    Saved,
  72    FileHandleChanged,
  73    Closed,
  74    DirtyChanged,
  75    DiagnosticsUpdated,
  76}
  77
  78#[derive(Clone)]
  79struct History {
  80    next_transaction_id: TransactionId,
  81    undo_stack: Vec<Transaction>,
  82    redo_stack: Vec<Transaction>,
  83    transaction_depth: usize,
  84    group_interval: Duration,
  85}
  86
  87#[derive(Clone)]
  88struct Transaction {
  89    id: TransactionId,
  90    buffer_transactions: HashMap<u64, text::TransactionId>,
  91    first_edit_at: Instant,
  92    last_edit_at: Instant,
  93    suppress_grouping: bool,
  94}
  95
  96pub trait ToOffset: 'static + fmt::Debug {
  97    fn to_offset(&self, snapshot: &MultiBufferSnapshot) -> usize;
  98}
  99
 100pub trait ToOffsetUtf16: 'static + fmt::Debug {
 101    fn to_offset_utf16(&self, snapshot: &MultiBufferSnapshot) -> OffsetUtf16;
 102}
 103
 104pub trait ToPoint: 'static + fmt::Debug {
 105    fn to_point(&self, snapshot: &MultiBufferSnapshot) -> Point;
 106}
 107
 108pub trait ToPointUtf16: 'static + fmt::Debug {
 109    fn to_point_utf16(&self, snapshot: &MultiBufferSnapshot) -> PointUtf16;
 110}
 111
 112struct BufferState {
 113    buffer: ModelHandle<Buffer>,
 114    last_version: clock::Global,
 115    last_parse_count: usize,
 116    last_selections_update_count: usize,
 117    last_diagnostics_update_count: usize,
 118    last_file_update_count: usize,
 119    last_git_diff_update_count: usize,
 120    excerpts: Vec<Locator>,
 121    _subscriptions: [gpui::Subscription; 2],
 122}
 123
 124#[derive(Clone, Default)]
 125pub struct MultiBufferSnapshot {
 126    singleton: bool,
 127    excerpts: SumTree<Excerpt>,
 128    excerpt_ids: SumTree<ExcerptIdMapping>,
 129    parse_count: usize,
 130    diagnostics_update_count: usize,
 131    trailing_excerpt_update_count: usize,
 132    git_diff_update_count: usize,
 133    edit_count: usize,
 134    is_dirty: bool,
 135    has_conflict: bool,
 136}
 137
 138pub struct ExcerptBoundary {
 139    pub id: ExcerptId,
 140    pub row: u32,
 141    pub buffer: BufferSnapshot,
 142    pub range: ExcerptRange<text::Anchor>,
 143    pub starts_new_buffer: bool,
 144}
 145
 146#[derive(Clone)]
 147struct Excerpt {
 148    id: ExcerptId,
 149    locator: Locator,
 150    buffer_id: u64,
 151    buffer: BufferSnapshot,
 152    range: ExcerptRange<text::Anchor>,
 153    max_buffer_row: u32,
 154    text_summary: TextSummary,
 155    has_trailing_newline: bool,
 156}
 157
 158#[derive(Clone, Debug)]
 159struct ExcerptIdMapping {
 160    id: ExcerptId,
 161    locator: Locator,
 162}
 163
 164#[derive(Clone, Debug, Eq, PartialEq)]
 165pub struct ExcerptRange<T> {
 166    pub context: Range<T>,
 167    pub primary: Option<Range<T>>,
 168}
 169
 170#[derive(Clone, Debug, Default)]
 171struct ExcerptSummary {
 172    excerpt_id: ExcerptId,
 173    excerpt_locator: Locator,
 174    max_buffer_row: u32,
 175    text: TextSummary,
 176}
 177
 178#[derive(Clone)]
 179pub struct MultiBufferRows<'a> {
 180    buffer_row_range: Range<u32>,
 181    excerpts: Cursor<'a, Excerpt, Point>,
 182}
 183
 184pub struct MultiBufferChunks<'a> {
 185    range: Range<usize>,
 186    excerpts: Cursor<'a, Excerpt, usize>,
 187    excerpt_chunks: Option<ExcerptChunks<'a>>,
 188    language_aware: bool,
 189}
 190
 191pub struct MultiBufferBytes<'a> {
 192    range: Range<usize>,
 193    excerpts: Cursor<'a, Excerpt, usize>,
 194    excerpt_bytes: Option<ExcerptBytes<'a>>,
 195    chunk: &'a [u8],
 196}
 197
 198struct ExcerptChunks<'a> {
 199    content_chunks: BufferChunks<'a>,
 200    footer_height: usize,
 201}
 202
 203struct ExcerptBytes<'a> {
 204    content_bytes: text::Bytes<'a>,
 205    footer_height: usize,
 206}
 207
 208impl MultiBuffer {
 209    pub fn new(replica_id: ReplicaId) -> Self {
 210        Self {
 211            snapshot: Default::default(),
 212            buffers: Default::default(),
 213            next_excerpt_id: 1,
 214            subscriptions: Default::default(),
 215            singleton: false,
 216            replica_id,
 217            history: History {
 218                next_transaction_id: Default::default(),
 219                undo_stack: Default::default(),
 220                redo_stack: Default::default(),
 221                transaction_depth: 0,
 222                group_interval: Duration::from_millis(300),
 223            },
 224            title: Default::default(),
 225        }
 226    }
 227
 228    pub fn clone(&self, new_cx: &mut ModelContext<Self>) -> Self {
 229        let mut buffers = HashMap::default();
 230        for (buffer_id, buffer_state) in self.buffers.borrow().iter() {
 231            buffers.insert(
 232                *buffer_id,
 233                BufferState {
 234                    buffer: buffer_state.buffer.clone(),
 235                    last_version: buffer_state.last_version.clone(),
 236                    last_parse_count: buffer_state.last_parse_count,
 237                    last_selections_update_count: buffer_state.last_selections_update_count,
 238                    last_diagnostics_update_count: buffer_state.last_diagnostics_update_count,
 239                    last_file_update_count: buffer_state.last_file_update_count,
 240                    last_git_diff_update_count: buffer_state.last_git_diff_update_count,
 241                    excerpts: buffer_state.excerpts.clone(),
 242                    _subscriptions: [
 243                        new_cx.observe(&buffer_state.buffer, |_, _, cx| cx.notify()),
 244                        new_cx.subscribe(&buffer_state.buffer, Self::on_buffer_event),
 245                    ],
 246                },
 247            );
 248        }
 249        Self {
 250            snapshot: RefCell::new(self.snapshot.borrow().clone()),
 251            buffers: RefCell::new(buffers),
 252            next_excerpt_id: 1,
 253            subscriptions: Default::default(),
 254            singleton: self.singleton,
 255            replica_id: self.replica_id,
 256            history: self.history.clone(),
 257            title: self.title.clone(),
 258        }
 259    }
 260
 261    pub fn with_title(mut self, title: String) -> Self {
 262        self.title = Some(title);
 263        self
 264    }
 265
 266    pub fn singleton(buffer: ModelHandle<Buffer>, cx: &mut ModelContext<Self>) -> Self {
 267        let mut this = Self::new(buffer.read(cx).replica_id());
 268        this.singleton = true;
 269        this.push_excerpts(
 270            buffer,
 271            [ExcerptRange {
 272                context: text::Anchor::MIN..text::Anchor::MAX,
 273                primary: None,
 274            }],
 275            cx,
 276        );
 277        this.snapshot.borrow_mut().singleton = true;
 278        this
 279    }
 280
 281    pub fn replica_id(&self) -> ReplicaId {
 282        self.replica_id
 283    }
 284
 285    pub fn snapshot(&self, cx: &AppContext) -> MultiBufferSnapshot {
 286        self.sync(cx);
 287        self.snapshot.borrow().clone()
 288    }
 289
 290    pub(crate) fn read(&self, cx: &AppContext) -> Ref<MultiBufferSnapshot> {
 291        self.sync(cx);
 292        self.snapshot.borrow()
 293    }
 294
 295    pub fn as_singleton(&self) -> Option<ModelHandle<Buffer>> {
 296        if self.singleton {
 297            return Some(
 298                self.buffers
 299                    .borrow()
 300                    .values()
 301                    .next()
 302                    .unwrap()
 303                    .buffer
 304                    .clone(),
 305            );
 306        } else {
 307            None
 308        }
 309    }
 310
 311    pub fn is_singleton(&self) -> bool {
 312        self.singleton
 313    }
 314
 315    pub fn subscribe(&mut self) -> Subscription {
 316        self.subscriptions.subscribe()
 317    }
 318
 319    pub fn is_dirty(&self, cx: &AppContext) -> bool {
 320        self.read(cx).is_dirty()
 321    }
 322
 323    pub fn has_conflict(&self, cx: &AppContext) -> bool {
 324        self.read(cx).has_conflict()
 325    }
 326
 327    // The `is_empty` signature doesn't match what clippy expects
 328    #[allow(clippy::len_without_is_empty)]
 329    pub fn len(&self, cx: &AppContext) -> usize {
 330        self.read(cx).len()
 331    }
 332
 333    pub fn is_empty(&self, cx: &AppContext) -> bool {
 334        self.len(cx) != 0
 335    }
 336
 337    pub fn symbols_containing<T: ToOffset>(
 338        &self,
 339        offset: T,
 340        theme: Option<&SyntaxTheme>,
 341        cx: &AppContext,
 342    ) -> Option<(u64, Vec<OutlineItem<Anchor>>)> {
 343        self.read(cx).symbols_containing(offset, theme)
 344    }
 345
 346    pub fn git_diff_recalc(&mut self, cx: &mut ModelContext<Self>) {
 347        let buffers = self.buffers.borrow();
 348        for buffer_state in buffers.values() {
 349            if buffer_state.buffer.read(cx).needs_git_diff_recalc() {
 350                buffer_state
 351                    .buffer
 352                    .update(cx, |buffer, cx| buffer.git_diff_recalc(cx))
 353            }
 354        }
 355    }
 356
 357    pub fn edit<I, S, T>(
 358        &mut self,
 359        edits: I,
 360        mut autoindent_mode: Option<AutoindentMode>,
 361        cx: &mut ModelContext<Self>,
 362    ) where
 363        I: IntoIterator<Item = (Range<S>, T)>,
 364        S: ToOffset,
 365        T: Into<Arc<str>>,
 366    {
 367        if self.buffers.borrow().is_empty() {
 368            return;
 369        }
 370
 371        let snapshot = self.read(cx);
 372        let edits = edits.into_iter().map(|(range, new_text)| {
 373            let mut range = range.start.to_offset(&snapshot)..range.end.to_offset(&snapshot);
 374            if range.start > range.end {
 375                mem::swap(&mut range.start, &mut range.end);
 376            }
 377            (range, new_text)
 378        });
 379
 380        if let Some(buffer) = self.as_singleton() {
 381            return buffer.update(cx, |buffer, cx| {
 382                buffer.edit(edits, autoindent_mode, cx);
 383            });
 384        }
 385
 386        let original_indent_columns = match &mut autoindent_mode {
 387            Some(AutoindentMode::Block {
 388                original_indent_columns,
 389            }) => mem::take(original_indent_columns),
 390            _ => Default::default(),
 391        };
 392
 393        struct BufferEdit {
 394            range: Range<usize>,
 395            new_text: Arc<str>,
 396            is_insertion: bool,
 397            original_indent_column: u32,
 398        }
 399        let mut buffer_edits: HashMap<u64, Vec<BufferEdit>> = Default::default();
 400        let mut cursor = snapshot.excerpts.cursor::<usize>();
 401        for (ix, (range, new_text)) in edits.enumerate() {
 402            let new_text: Arc<str> = new_text.into();
 403            let original_indent_column = original_indent_columns.get(ix).copied().unwrap_or(0);
 404            cursor.seek(&range.start, Bias::Right, &());
 405            if cursor.item().is_none() && range.start == *cursor.start() {
 406                cursor.prev(&());
 407            }
 408            let start_excerpt = cursor.item().expect("start offset out of bounds");
 409            let start_overshoot = range.start - cursor.start();
 410            let buffer_start = start_excerpt
 411                .range
 412                .context
 413                .start
 414                .to_offset(&start_excerpt.buffer)
 415                + start_overshoot;
 416
 417            cursor.seek(&range.end, Bias::Right, &());
 418            if cursor.item().is_none() && range.end == *cursor.start() {
 419                cursor.prev(&());
 420            }
 421            let end_excerpt = cursor.item().expect("end offset out of bounds");
 422            let end_overshoot = range.end - cursor.start();
 423            let buffer_end = end_excerpt
 424                .range
 425                .context
 426                .start
 427                .to_offset(&end_excerpt.buffer)
 428                + end_overshoot;
 429
 430            if start_excerpt.id == end_excerpt.id {
 431                buffer_edits
 432                    .entry(start_excerpt.buffer_id)
 433                    .or_insert(Vec::new())
 434                    .push(BufferEdit {
 435                        range: buffer_start..buffer_end,
 436                        new_text,
 437                        is_insertion: true,
 438                        original_indent_column,
 439                    });
 440            } else {
 441                let start_excerpt_range = buffer_start
 442                    ..start_excerpt
 443                        .range
 444                        .context
 445                        .end
 446                        .to_offset(&start_excerpt.buffer);
 447                let end_excerpt_range = end_excerpt
 448                    .range
 449                    .context
 450                    .start
 451                    .to_offset(&end_excerpt.buffer)
 452                    ..buffer_end;
 453                buffer_edits
 454                    .entry(start_excerpt.buffer_id)
 455                    .or_insert(Vec::new())
 456                    .push(BufferEdit {
 457                        range: start_excerpt_range,
 458                        new_text: new_text.clone(),
 459                        is_insertion: true,
 460                        original_indent_column,
 461                    });
 462                buffer_edits
 463                    .entry(end_excerpt.buffer_id)
 464                    .or_insert(Vec::new())
 465                    .push(BufferEdit {
 466                        range: end_excerpt_range,
 467                        new_text: new_text.clone(),
 468                        is_insertion: false,
 469                        original_indent_column,
 470                    });
 471
 472                cursor.seek(&range.start, Bias::Right, &());
 473                cursor.next(&());
 474                while let Some(excerpt) = cursor.item() {
 475                    if excerpt.id == end_excerpt.id {
 476                        break;
 477                    }
 478                    buffer_edits
 479                        .entry(excerpt.buffer_id)
 480                        .or_insert(Vec::new())
 481                        .push(BufferEdit {
 482                            range: excerpt.range.context.to_offset(&excerpt.buffer),
 483                            new_text: new_text.clone(),
 484                            is_insertion: false,
 485                            original_indent_column,
 486                        });
 487                    cursor.next(&());
 488                }
 489            }
 490        }
 491
 492        for (buffer_id, mut edits) in buffer_edits {
 493            edits.sort_unstable_by_key(|edit| edit.range.start);
 494            self.buffers.borrow()[&buffer_id]
 495                .buffer
 496                .update(cx, |buffer, cx| {
 497                    let mut edits = edits.into_iter().peekable();
 498                    let mut insertions = Vec::new();
 499                    let mut original_indent_columns = Vec::new();
 500                    let mut deletions = Vec::new();
 501                    let empty_str: Arc<str> = "".into();
 502                    while let Some(BufferEdit {
 503                        mut range,
 504                        new_text,
 505                        mut is_insertion,
 506                        original_indent_column,
 507                    }) = edits.next()
 508                    {
 509                        while let Some(BufferEdit {
 510                            range: next_range,
 511                            is_insertion: next_is_insertion,
 512                            ..
 513                        }) = edits.peek()
 514                        {
 515                            if range.end >= next_range.start {
 516                                range.end = cmp::max(next_range.end, range.end);
 517                                is_insertion |= *next_is_insertion;
 518                                edits.next();
 519                            } else {
 520                                break;
 521                            }
 522                        }
 523
 524                        if is_insertion {
 525                            original_indent_columns.push(original_indent_column);
 526                            insertions.push((
 527                                buffer.anchor_before(range.start)..buffer.anchor_before(range.end),
 528                                new_text.clone(),
 529                            ));
 530                        } else if !range.is_empty() {
 531                            deletions.push((
 532                                buffer.anchor_before(range.start)..buffer.anchor_before(range.end),
 533                                empty_str.clone(),
 534                            ));
 535                        }
 536                    }
 537
 538                    let deletion_autoindent_mode =
 539                        if let Some(AutoindentMode::Block { .. }) = autoindent_mode {
 540                            Some(AutoindentMode::Block {
 541                                original_indent_columns: Default::default(),
 542                            })
 543                        } else {
 544                            None
 545                        };
 546                    let insertion_autoindent_mode =
 547                        if let Some(AutoindentMode::Block { .. }) = autoindent_mode {
 548                            Some(AutoindentMode::Block {
 549                                original_indent_columns,
 550                            })
 551                        } else {
 552                            None
 553                        };
 554
 555                    buffer.edit(deletions, deletion_autoindent_mode, cx);
 556                    buffer.edit(insertions, insertion_autoindent_mode, cx);
 557                })
 558        }
 559    }
 560
 561    pub fn start_transaction(&mut self, cx: &mut ModelContext<Self>) -> Option<TransactionId> {
 562        self.start_transaction_at(Instant::now(), cx)
 563    }
 564
 565    pub(crate) fn start_transaction_at(
 566        &mut self,
 567        now: Instant,
 568        cx: &mut ModelContext<Self>,
 569    ) -> Option<TransactionId> {
 570        if let Some(buffer) = self.as_singleton() {
 571            return buffer.update(cx, |buffer, _| buffer.start_transaction_at(now));
 572        }
 573
 574        for BufferState { buffer, .. } in self.buffers.borrow().values() {
 575            buffer.update(cx, |buffer, _| buffer.start_transaction_at(now));
 576        }
 577        self.history.start_transaction(now)
 578    }
 579
 580    pub fn end_transaction(&mut self, cx: &mut ModelContext<Self>) -> Option<TransactionId> {
 581        self.end_transaction_at(Instant::now(), cx)
 582    }
 583
 584    pub(crate) fn end_transaction_at(
 585        &mut self,
 586        now: Instant,
 587        cx: &mut ModelContext<Self>,
 588    ) -> Option<TransactionId> {
 589        if let Some(buffer) = self.as_singleton() {
 590            return buffer.update(cx, |buffer, cx| buffer.end_transaction_at(now, cx));
 591        }
 592
 593        let mut buffer_transactions = HashMap::default();
 594        for BufferState { buffer, .. } in self.buffers.borrow().values() {
 595            if let Some(transaction_id) =
 596                buffer.update(cx, |buffer, cx| buffer.end_transaction_at(now, cx))
 597            {
 598                buffer_transactions.insert(buffer.read(cx).remote_id(), transaction_id);
 599            }
 600        }
 601
 602        if self.history.end_transaction(now, buffer_transactions) {
 603            let transaction_id = self.history.group().unwrap();
 604            Some(transaction_id)
 605        } else {
 606            None
 607        }
 608    }
 609
 610    pub fn finalize_last_transaction(&mut self, cx: &mut ModelContext<Self>) {
 611        self.history.finalize_last_transaction();
 612        for BufferState { buffer, .. } in self.buffers.borrow().values() {
 613            buffer.update(cx, |buffer, _| {
 614                buffer.finalize_last_transaction();
 615            });
 616        }
 617    }
 618
 619    pub fn push_transaction<'a, T>(&mut self, buffer_transactions: T, cx: &mut ModelContext<Self>)
 620    where
 621        T: IntoIterator<Item = (&'a ModelHandle<Buffer>, &'a language::Transaction)>,
 622    {
 623        self.history
 624            .push_transaction(buffer_transactions, Instant::now(), cx);
 625        self.history.finalize_last_transaction();
 626    }
 627
 628    pub fn group_until_transaction(
 629        &mut self,
 630        transaction_id: TransactionId,
 631        cx: &mut ModelContext<Self>,
 632    ) {
 633        if let Some(buffer) = self.as_singleton() {
 634            buffer.update(cx, |buffer, _| {
 635                buffer.group_until_transaction(transaction_id)
 636            });
 637        } else {
 638            self.history.group_until(transaction_id);
 639        }
 640    }
 641
 642    pub fn set_active_selections(
 643        &mut self,
 644        selections: &[Selection<Anchor>],
 645        line_mode: bool,
 646        cursor_shape: CursorShape,
 647        cx: &mut ModelContext<Self>,
 648    ) {
 649        let mut selections_by_buffer: HashMap<u64, Vec<Selection<text::Anchor>>> =
 650            Default::default();
 651        let snapshot = self.read(cx);
 652        let mut cursor = snapshot.excerpts.cursor::<Option<&Locator>>();
 653        for selection in selections {
 654            let start_locator = snapshot.excerpt_locator_for_id(selection.start.excerpt_id);
 655            let end_locator = snapshot.excerpt_locator_for_id(selection.end.excerpt_id);
 656
 657            cursor.seek(&Some(start_locator), Bias::Left, &());
 658            while let Some(excerpt) = cursor.item() {
 659                if excerpt.locator > *end_locator {
 660                    break;
 661                }
 662
 663                let mut start = excerpt.range.context.start;
 664                let mut end = excerpt.range.context.end;
 665                if excerpt.id == selection.start.excerpt_id {
 666                    start = selection.start.text_anchor;
 667                }
 668                if excerpt.id == selection.end.excerpt_id {
 669                    end = selection.end.text_anchor;
 670                }
 671                selections_by_buffer
 672                    .entry(excerpt.buffer_id)
 673                    .or_default()
 674                    .push(Selection {
 675                        id: selection.id,
 676                        start,
 677                        end,
 678                        reversed: selection.reversed,
 679                        goal: selection.goal,
 680                    });
 681
 682                cursor.next(&());
 683            }
 684        }
 685
 686        for (buffer_id, buffer_state) in self.buffers.borrow().iter() {
 687            if !selections_by_buffer.contains_key(buffer_id) {
 688                buffer_state
 689                    .buffer
 690                    .update(cx, |buffer, cx| buffer.remove_active_selections(cx));
 691            }
 692        }
 693
 694        for (buffer_id, mut selections) in selections_by_buffer {
 695            self.buffers.borrow()[&buffer_id]
 696                .buffer
 697                .update(cx, |buffer, cx| {
 698                    selections.sort_unstable_by(|a, b| a.start.cmp(&b.start, buffer));
 699                    let mut selections = selections.into_iter().peekable();
 700                    let merged_selections = Arc::from_iter(iter::from_fn(|| {
 701                        let mut selection = selections.next()?;
 702                        while let Some(next_selection) = selections.peek() {
 703                            if selection.end.cmp(&next_selection.start, buffer).is_ge() {
 704                                let next_selection = selections.next().unwrap();
 705                                if next_selection.end.cmp(&selection.end, buffer).is_ge() {
 706                                    selection.end = next_selection.end;
 707                                }
 708                            } else {
 709                                break;
 710                            }
 711                        }
 712                        Some(selection)
 713                    }));
 714                    buffer.set_active_selections(merged_selections, line_mode, cursor_shape, cx);
 715                });
 716        }
 717    }
 718
 719    pub fn remove_active_selections(&mut self, cx: &mut ModelContext<Self>) {
 720        for buffer in self.buffers.borrow().values() {
 721            buffer
 722                .buffer
 723                .update(cx, |buffer, cx| buffer.remove_active_selections(cx));
 724        }
 725    }
 726
 727    pub fn undo(&mut self, cx: &mut ModelContext<Self>) -> Option<TransactionId> {
 728        if let Some(buffer) = self.as_singleton() {
 729            return buffer.update(cx, |buffer, cx| buffer.undo(cx));
 730        }
 731
 732        while let Some(transaction) = self.history.pop_undo() {
 733            let mut undone = false;
 734            for (buffer_id, buffer_transaction_id) in &mut transaction.buffer_transactions {
 735                if let Some(BufferState { buffer, .. }) = self.buffers.borrow().get(buffer_id) {
 736                    undone |= buffer.update(cx, |buffer, cx| {
 737                        let undo_to = *buffer_transaction_id;
 738                        if let Some(entry) = buffer.peek_undo_stack() {
 739                            *buffer_transaction_id = entry.transaction_id();
 740                        }
 741                        buffer.undo_to_transaction(undo_to, cx)
 742                    });
 743                }
 744            }
 745
 746            if undone {
 747                return Some(transaction.id);
 748            }
 749        }
 750
 751        None
 752    }
 753
 754    pub fn redo(&mut self, cx: &mut ModelContext<Self>) -> Option<TransactionId> {
 755        if let Some(buffer) = self.as_singleton() {
 756            return buffer.update(cx, |buffer, cx| buffer.redo(cx));
 757        }
 758
 759        while let Some(transaction) = self.history.pop_redo() {
 760            let mut redone = false;
 761            for (buffer_id, buffer_transaction_id) in &mut transaction.buffer_transactions {
 762                if let Some(BufferState { buffer, .. }) = self.buffers.borrow().get(buffer_id) {
 763                    redone |= buffer.update(cx, |buffer, cx| {
 764                        let redo_to = *buffer_transaction_id;
 765                        if let Some(entry) = buffer.peek_redo_stack() {
 766                            *buffer_transaction_id = entry.transaction_id();
 767                        }
 768                        buffer.redo_to_transaction(redo_to, cx)
 769                    });
 770                }
 771            }
 772
 773            if redone {
 774                return Some(transaction.id);
 775            }
 776        }
 777
 778        None
 779    }
 780
 781    pub fn stream_excerpts_with_context_lines(
 782        &mut self,
 783        excerpts: Vec<(ModelHandle<Buffer>, Vec<Range<text::Anchor>>)>,
 784        context_line_count: u32,
 785        cx: &mut ModelContext<Self>,
 786    ) -> (Task<()>, mpsc::Receiver<Range<Anchor>>) {
 787        let (mut tx, rx) = mpsc::channel(256);
 788        let task = cx.spawn(|this, mut cx| async move {
 789            for (buffer, ranges) in excerpts {
 790                let (buffer_id, buffer_snapshot) =
 791                    buffer.read_with(&cx, |buffer, _| (buffer.remote_id(), buffer.snapshot()));
 792
 793                let mut excerpt_ranges = Vec::new();
 794                let mut range_counts = Vec::new();
 795                cx.background()
 796                    .scoped(|scope| {
 797                        scope.spawn(async {
 798                            let (ranges, counts) =
 799                                build_excerpt_ranges(&buffer_snapshot, &ranges, context_line_count);
 800                            excerpt_ranges = ranges;
 801                            range_counts = counts;
 802                        });
 803                    })
 804                    .await;
 805
 806                let mut ranges = ranges.into_iter();
 807                let mut range_counts = range_counts.into_iter();
 808                for excerpt_ranges in excerpt_ranges.chunks(100) {
 809                    let excerpt_ids = this.update(&mut cx, |this, cx| {
 810                        this.push_excerpts(buffer.clone(), excerpt_ranges.iter().cloned(), cx)
 811                    });
 812
 813                    for (excerpt_id, range_count) in
 814                        excerpt_ids.into_iter().zip(range_counts.by_ref())
 815                    {
 816                        for range in ranges.by_ref().take(range_count) {
 817                            let start = Anchor {
 818                                buffer_id: Some(buffer_id),
 819                                excerpt_id: excerpt_id.clone(),
 820                                text_anchor: range.start,
 821                            };
 822                            let end = Anchor {
 823                                buffer_id: Some(buffer_id),
 824                                excerpt_id: excerpt_id.clone(),
 825                                text_anchor: range.end,
 826                            };
 827                            if tx.send(start..end).await.is_err() {
 828                                break;
 829                            }
 830                        }
 831                    }
 832                }
 833            }
 834        });
 835        (task, rx)
 836    }
 837
 838    pub fn push_excerpts<O>(
 839        &mut self,
 840        buffer: ModelHandle<Buffer>,
 841        ranges: impl IntoIterator<Item = ExcerptRange<O>>,
 842        cx: &mut ModelContext<Self>,
 843    ) -> Vec<ExcerptId>
 844    where
 845        O: text::ToOffset,
 846    {
 847        self.insert_excerpts_after(ExcerptId::max(), buffer, ranges, cx)
 848    }
 849
 850    pub fn push_excerpts_with_context_lines<O>(
 851        &mut self,
 852        buffer: ModelHandle<Buffer>,
 853        ranges: Vec<Range<O>>,
 854        context_line_count: u32,
 855        cx: &mut ModelContext<Self>,
 856    ) -> Vec<Range<Anchor>>
 857    where
 858        O: text::ToPoint + text::ToOffset,
 859    {
 860        let buffer_id = buffer.read(cx).remote_id();
 861        let buffer_snapshot = buffer.read(cx).snapshot();
 862        let (excerpt_ranges, range_counts) =
 863            build_excerpt_ranges(&buffer_snapshot, &ranges, context_line_count);
 864
 865        let excerpt_ids = self.push_excerpts(buffer, excerpt_ranges, cx);
 866
 867        let mut anchor_ranges = Vec::new();
 868        let mut ranges = ranges.into_iter();
 869        for (excerpt_id, range_count) in excerpt_ids.into_iter().zip(range_counts.into_iter()) {
 870            anchor_ranges.extend(ranges.by_ref().take(range_count).map(|range| {
 871                let start = Anchor {
 872                    buffer_id: Some(buffer_id),
 873                    excerpt_id: excerpt_id.clone(),
 874                    text_anchor: buffer_snapshot.anchor_after(range.start),
 875                };
 876                let end = Anchor {
 877                    buffer_id: Some(buffer_id),
 878                    excerpt_id: excerpt_id.clone(),
 879                    text_anchor: buffer_snapshot.anchor_after(range.end),
 880                };
 881                start..end
 882            }))
 883        }
 884        anchor_ranges
 885    }
 886
 887    pub fn insert_excerpts_after<O>(
 888        &mut self,
 889        prev_excerpt_id: ExcerptId,
 890        buffer: ModelHandle<Buffer>,
 891        ranges: impl IntoIterator<Item = ExcerptRange<O>>,
 892        cx: &mut ModelContext<Self>,
 893    ) -> Vec<ExcerptId>
 894    where
 895        O: text::ToOffset,
 896    {
 897        let mut ids = Vec::new();
 898        let mut next_excerpt_id = self.next_excerpt_id;
 899        self.insert_excerpts_with_ids_after(
 900            prev_excerpt_id,
 901            buffer,
 902            ranges.into_iter().map(|range| {
 903                let id = ExcerptId(post_inc(&mut next_excerpt_id));
 904                ids.push(id);
 905                (id, range)
 906            }),
 907            cx,
 908        );
 909        ids
 910    }
 911
 912    pub fn insert_excerpts_with_ids_after<O>(
 913        &mut self,
 914        prev_excerpt_id: ExcerptId,
 915        buffer: ModelHandle<Buffer>,
 916        ranges: impl IntoIterator<Item = (ExcerptId, ExcerptRange<O>)>,
 917        cx: &mut ModelContext<Self>,
 918    ) where
 919        O: text::ToOffset,
 920    {
 921        assert_eq!(self.history.transaction_depth, 0);
 922        let mut ranges = ranges.into_iter().peekable();
 923        if ranges.peek().is_none() {
 924            return Default::default();
 925        }
 926
 927        self.sync(cx);
 928
 929        let buffer_id = buffer.read(cx).remote_id();
 930        let buffer_snapshot = buffer.read(cx).snapshot();
 931
 932        let mut buffers = self.buffers.borrow_mut();
 933        let buffer_state = buffers.entry(buffer_id).or_insert_with(|| BufferState {
 934            last_version: buffer_snapshot.version().clone(),
 935            last_parse_count: buffer_snapshot.parse_count(),
 936            last_selections_update_count: buffer_snapshot.selections_update_count(),
 937            last_diagnostics_update_count: buffer_snapshot.diagnostics_update_count(),
 938            last_file_update_count: buffer_snapshot.file_update_count(),
 939            last_git_diff_update_count: buffer_snapshot.git_diff_update_count(),
 940            excerpts: Default::default(),
 941            _subscriptions: [
 942                cx.observe(&buffer, |_, _, cx| cx.notify()),
 943                cx.subscribe(&buffer, Self::on_buffer_event),
 944            ],
 945            buffer: buffer.clone(),
 946        });
 947
 948        let mut snapshot = self.snapshot.borrow_mut();
 949
 950        let mut prev_locator = snapshot.excerpt_locator_for_id(prev_excerpt_id).clone();
 951        let mut new_excerpt_ids = mem::take(&mut snapshot.excerpt_ids);
 952        let mut cursor = snapshot.excerpts.cursor::<Option<&Locator>>();
 953        let mut new_excerpts = cursor.slice(&prev_locator, Bias::Right, &());
 954        prev_locator = cursor.start().unwrap_or(Locator::min_ref()).clone();
 955
 956        let edit_start = new_excerpts.summary().text.len;
 957        new_excerpts.update_last(
 958            |excerpt| {
 959                excerpt.has_trailing_newline = true;
 960            },
 961            &(),
 962        );
 963
 964        let next_locator = if let Some(excerpt) = cursor.item() {
 965            excerpt.locator.clone()
 966        } else {
 967            Locator::max()
 968        };
 969
 970        let mut excerpts = Vec::new();
 971        while let Some((id, range)) = ranges.next() {
 972            let locator = Locator::between(&prev_locator, &next_locator);
 973            if let Err(ix) = buffer_state.excerpts.binary_search(&locator) {
 974                buffer_state.excerpts.insert(ix, locator.clone());
 975            }
 976            let range = ExcerptRange {
 977                context: buffer_snapshot.anchor_before(&range.context.start)
 978                    ..buffer_snapshot.anchor_after(&range.context.end),
 979                primary: range.primary.map(|primary| {
 980                    buffer_snapshot.anchor_before(&primary.start)
 981                        ..buffer_snapshot.anchor_after(&primary.end)
 982                }),
 983            };
 984            if id.0 >= self.next_excerpt_id {
 985                self.next_excerpt_id = id.0 + 1;
 986            }
 987            excerpts.push((id, range.clone()));
 988            let excerpt = Excerpt::new(
 989                id,
 990                locator.clone(),
 991                buffer_id,
 992                buffer_snapshot.clone(),
 993                range,
 994                ranges.peek().is_some() || cursor.item().is_some(),
 995            );
 996            new_excerpts.push(excerpt, &());
 997            prev_locator = locator.clone();
 998            new_excerpt_ids.push(ExcerptIdMapping { id, locator }, &());
 999        }
1000
1001        let edit_end = new_excerpts.summary().text.len;
1002
1003        let suffix = cursor.suffix(&());
1004        let changed_trailing_excerpt = suffix.is_empty();
1005        new_excerpts.push_tree(suffix, &());
1006        drop(cursor);
1007        snapshot.excerpts = new_excerpts;
1008        snapshot.excerpt_ids = new_excerpt_ids;
1009        if changed_trailing_excerpt {
1010            snapshot.trailing_excerpt_update_count += 1;
1011        }
1012
1013        self.subscriptions.publish_mut([Edit {
1014            old: edit_start..edit_start,
1015            new: edit_start..edit_end,
1016        }]);
1017        cx.emit(Event::Edited);
1018        cx.emit(Event::ExcerptsAdded {
1019            buffer,
1020            predecessor: prev_excerpt_id,
1021            excerpts,
1022        });
1023        cx.notify();
1024    }
1025
1026    pub fn clear(&mut self, cx: &mut ModelContext<Self>) {
1027        self.sync(cx);
1028        let ids = self.excerpt_ids();
1029        self.buffers.borrow_mut().clear();
1030        let mut snapshot = self.snapshot.borrow_mut();
1031        let prev_len = snapshot.len();
1032        snapshot.excerpts = Default::default();
1033        snapshot.trailing_excerpt_update_count += 1;
1034        snapshot.is_dirty = false;
1035        snapshot.has_conflict = false;
1036
1037        self.subscriptions.publish_mut([Edit {
1038            old: 0..prev_len,
1039            new: 0..0,
1040        }]);
1041        cx.emit(Event::Edited);
1042        cx.emit(Event::ExcerptsRemoved { ids });
1043        cx.notify();
1044    }
1045
1046    pub fn excerpts_for_buffer(
1047        &self,
1048        buffer: &ModelHandle<Buffer>,
1049        cx: &AppContext,
1050    ) -> Vec<(ExcerptId, ExcerptRange<text::Anchor>)> {
1051        let mut excerpts = Vec::new();
1052        let snapshot = self.read(cx);
1053        let buffers = self.buffers.borrow();
1054        let mut cursor = snapshot.excerpts.cursor::<Option<&Locator>>();
1055        for locator in buffers
1056            .get(&buffer.read(cx).remote_id())
1057            .map(|state| &state.excerpts)
1058            .into_iter()
1059            .flatten()
1060        {
1061            cursor.seek_forward(&Some(locator), Bias::Left, &());
1062            if let Some(excerpt) = cursor.item() {
1063                if excerpt.locator == *locator {
1064                    excerpts.push((excerpt.id.clone(), excerpt.range.clone()));
1065                }
1066            }
1067        }
1068
1069        excerpts
1070    }
1071
1072    pub fn excerpt_ids(&self) -> Vec<ExcerptId> {
1073        self.snapshot
1074            .borrow()
1075            .excerpts
1076            .iter()
1077            .map(|entry| entry.id)
1078            .collect()
1079    }
1080
1081    pub fn excerpt_containing(
1082        &self,
1083        position: impl ToOffset,
1084        cx: &AppContext,
1085    ) -> Option<(ExcerptId, ModelHandle<Buffer>, Range<text::Anchor>)> {
1086        let snapshot = self.read(cx);
1087        let position = position.to_offset(&snapshot);
1088
1089        let mut cursor = snapshot.excerpts.cursor::<usize>();
1090        cursor.seek(&position, Bias::Right, &());
1091        cursor
1092            .item()
1093            .or_else(|| snapshot.excerpts.last())
1094            .map(|excerpt| {
1095                (
1096                    excerpt.id.clone(),
1097                    self.buffers
1098                        .borrow()
1099                        .get(&excerpt.buffer_id)
1100                        .unwrap()
1101                        .buffer
1102                        .clone(),
1103                    excerpt.range.context.clone(),
1104                )
1105            })
1106    }
1107
1108    // If point is at the end of the buffer, the last excerpt is returned
1109    pub fn point_to_buffer_offset<T: ToOffset>(
1110        &self,
1111        point: T,
1112        cx: &AppContext,
1113    ) -> Option<(ModelHandle<Buffer>, usize)> {
1114        let snapshot = self.read(cx);
1115        let offset = point.to_offset(&snapshot);
1116        let mut cursor = snapshot.excerpts.cursor::<usize>();
1117        cursor.seek(&offset, Bias::Right, &());
1118        if cursor.item().is_none() {
1119            cursor.prev(&());
1120        }
1121
1122        cursor.item().map(|excerpt| {
1123            let excerpt_start = excerpt.range.context.start.to_offset(&excerpt.buffer);
1124            let buffer_point = excerpt_start + offset - *cursor.start();
1125            let buffer = self.buffers.borrow()[&excerpt.buffer_id].buffer.clone();
1126
1127            (buffer, buffer_point)
1128        })
1129    }
1130
1131    pub fn range_to_buffer_ranges<T: ToOffset>(
1132        &self,
1133        range: Range<T>,
1134        cx: &AppContext,
1135    ) -> Vec<(ModelHandle<Buffer>, Range<usize>)> {
1136        let snapshot = self.read(cx);
1137        let start = range.start.to_offset(&snapshot);
1138        let end = range.end.to_offset(&snapshot);
1139
1140        let mut result = Vec::new();
1141        let mut cursor = snapshot.excerpts.cursor::<usize>();
1142        cursor.seek(&start, Bias::Right, &());
1143        if cursor.item().is_none() {
1144            cursor.prev(&());
1145        }
1146
1147        while let Some(excerpt) = cursor.item() {
1148            if *cursor.start() > end {
1149                break;
1150            }
1151
1152            let mut end_before_newline = cursor.end(&());
1153            if excerpt.has_trailing_newline {
1154                end_before_newline -= 1;
1155            }
1156            let excerpt_start = excerpt.range.context.start.to_offset(&excerpt.buffer);
1157            let start = excerpt_start + (cmp::max(start, *cursor.start()) - *cursor.start());
1158            let end = excerpt_start + (cmp::min(end, end_before_newline) - *cursor.start());
1159            let buffer = self.buffers.borrow()[&excerpt.buffer_id].buffer.clone();
1160            result.push((buffer, start..end));
1161            cursor.next(&());
1162        }
1163
1164        result
1165    }
1166
1167    pub fn remove_excerpts(
1168        &mut self,
1169        excerpt_ids: impl IntoIterator<Item = ExcerptId>,
1170        cx: &mut ModelContext<Self>,
1171    ) {
1172        self.sync(cx);
1173        let ids = excerpt_ids.into_iter().collect::<Vec<_>>();
1174        if ids.is_empty() {
1175            return;
1176        }
1177
1178        let mut buffers = self.buffers.borrow_mut();
1179        let mut snapshot = self.snapshot.borrow_mut();
1180        let mut new_excerpts = SumTree::new();
1181        let mut cursor = snapshot.excerpts.cursor::<(Option<&Locator>, usize)>();
1182        let mut edits = Vec::new();
1183        let mut excerpt_ids = ids.iter().copied().peekable();
1184
1185        while let Some(excerpt_id) = excerpt_ids.next() {
1186            // Seek to the next excerpt to remove, preserving any preceding excerpts.
1187            let locator = snapshot.excerpt_locator_for_id(excerpt_id);
1188            new_excerpts.push_tree(cursor.slice(&Some(locator), Bias::Left, &()), &());
1189
1190            if let Some(mut excerpt) = cursor.item() {
1191                if excerpt.id != excerpt_id {
1192                    continue;
1193                }
1194                let mut old_start = cursor.start().1;
1195
1196                // Skip over the removed excerpt.
1197                'remove_excerpts: loop {
1198                    if let Some(buffer_state) = buffers.get_mut(&excerpt.buffer_id) {
1199                        buffer_state.excerpts.retain(|l| l != &excerpt.locator);
1200                        if buffer_state.excerpts.is_empty() {
1201                            buffers.remove(&excerpt.buffer_id);
1202                        }
1203                    }
1204                    cursor.next(&());
1205
1206                    // Skip over any subsequent excerpts that are also removed.
1207                    while let Some(&next_excerpt_id) = excerpt_ids.peek() {
1208                        let next_locator = snapshot.excerpt_locator_for_id(next_excerpt_id);
1209                        if let Some(next_excerpt) = cursor.item() {
1210                            if next_excerpt.locator == *next_locator {
1211                                excerpt_ids.next();
1212                                excerpt = next_excerpt;
1213                                continue 'remove_excerpts;
1214                            }
1215                        }
1216                        break;
1217                    }
1218
1219                    break;
1220                }
1221
1222                // When removing the last excerpt, remove the trailing newline from
1223                // the previous excerpt.
1224                if cursor.item().is_none() && old_start > 0 {
1225                    old_start -= 1;
1226                    new_excerpts.update_last(|e| e.has_trailing_newline = false, &());
1227                }
1228
1229                // Push an edit for the removal of this run of excerpts.
1230                let old_end = cursor.start().1;
1231                let new_start = new_excerpts.summary().text.len;
1232                edits.push(Edit {
1233                    old: old_start..old_end,
1234                    new: new_start..new_start,
1235                });
1236            }
1237        }
1238        let suffix = cursor.suffix(&());
1239        let changed_trailing_excerpt = suffix.is_empty();
1240        new_excerpts.push_tree(suffix, &());
1241        drop(cursor);
1242        snapshot.excerpts = new_excerpts;
1243
1244        if changed_trailing_excerpt {
1245            snapshot.trailing_excerpt_update_count += 1;
1246        }
1247
1248        self.subscriptions.publish_mut(edits);
1249        cx.emit(Event::Edited);
1250        cx.emit(Event::ExcerptsRemoved { ids });
1251        cx.notify();
1252    }
1253
1254    pub fn wait_for_anchors<'a>(
1255        &self,
1256        anchors: impl 'a + Iterator<Item = Anchor>,
1257        cx: &mut ModelContext<Self>,
1258    ) -> impl 'static + Future<Output = Result<()>> {
1259        let borrow = self.buffers.borrow();
1260        let mut error = None;
1261        let mut futures = Vec::new();
1262        for anchor in anchors {
1263            if let Some(buffer_id) = anchor.buffer_id {
1264                if let Some(buffer) = borrow.get(&buffer_id) {
1265                    buffer.buffer.update(cx, |buffer, _| {
1266                        futures.push(buffer.wait_for_anchors([anchor.text_anchor]))
1267                    });
1268                } else {
1269                    error = Some(anyhow!(
1270                        "buffer {buffer_id} is not part of this multi-buffer"
1271                    ));
1272                    break;
1273                }
1274            }
1275        }
1276        async move {
1277            if let Some(error) = error {
1278                Err(error)?;
1279            }
1280            for future in futures {
1281                future.await?;
1282            }
1283            Ok(())
1284        }
1285    }
1286
1287    pub fn text_anchor_for_position<T: ToOffset>(
1288        &self,
1289        position: T,
1290        cx: &AppContext,
1291    ) -> Option<(ModelHandle<Buffer>, language::Anchor)> {
1292        let snapshot = self.read(cx);
1293        let anchor = snapshot.anchor_before(position);
1294        let buffer = self
1295            .buffers
1296            .borrow()
1297            .get(&anchor.buffer_id?)?
1298            .buffer
1299            .clone();
1300        Some((buffer, anchor.text_anchor))
1301    }
1302
1303    fn on_buffer_event(
1304        &mut self,
1305        _: ModelHandle<Buffer>,
1306        event: &language::Event,
1307        cx: &mut ModelContext<Self>,
1308    ) {
1309        cx.emit(match event {
1310            language::Event::Edited => Event::Edited,
1311            language::Event::DirtyChanged => Event::DirtyChanged,
1312            language::Event::Saved => Event::Saved,
1313            language::Event::FileHandleChanged => Event::FileHandleChanged,
1314            language::Event::Reloaded => Event::Reloaded,
1315            language::Event::LanguageChanged => Event::LanguageChanged,
1316            language::Event::Reparsed => Event::Reparsed,
1317            language::Event::DiagnosticsUpdated => Event::DiagnosticsUpdated,
1318            language::Event::Closed => Event::Closed,
1319
1320            //
1321            language::Event::Operation(_) => return,
1322        });
1323    }
1324
1325    pub fn all_buffers(&self) -> HashSet<ModelHandle<Buffer>> {
1326        self.buffers
1327            .borrow()
1328            .values()
1329            .map(|state| state.buffer.clone())
1330            .collect()
1331    }
1332
1333    pub fn buffer(&self, buffer_id: u64) -> Option<ModelHandle<Buffer>> {
1334        self.buffers
1335            .borrow()
1336            .get(&buffer_id)
1337            .map(|state| state.buffer.clone())
1338    }
1339
1340    pub fn is_completion_trigger<T>(&self, position: T, text: &str, cx: &AppContext) -> bool
1341    where
1342        T: ToOffset,
1343    {
1344        let mut chars = text.chars();
1345        let char = if let Some(char) = chars.next() {
1346            char
1347        } else {
1348            return false;
1349        };
1350        if chars.next().is_some() {
1351            return false;
1352        }
1353
1354        if char.is_alphanumeric() || char == '_' {
1355            return true;
1356        }
1357
1358        let snapshot = self.snapshot(cx);
1359        let anchor = snapshot.anchor_before(position);
1360        anchor
1361            .buffer_id
1362            .and_then(|buffer_id| {
1363                let buffer = self.buffers.borrow().get(&buffer_id)?.buffer.clone();
1364                Some(
1365                    buffer
1366                        .read(cx)
1367                        .completion_triggers()
1368                        .iter()
1369                        .any(|string| string == text),
1370                )
1371            })
1372            .unwrap_or(false)
1373    }
1374
1375    pub fn language_at<'a, T: ToOffset>(
1376        &self,
1377        point: T,
1378        cx: &'a AppContext,
1379    ) -> Option<Arc<Language>> {
1380        self.point_to_buffer_offset(point, cx)
1381            .and_then(|(buffer, offset)| buffer.read(cx).language_at(offset))
1382    }
1383
1384    pub fn settings_at<'a, T: ToOffset>(
1385        &self,
1386        point: T,
1387        cx: &'a AppContext,
1388    ) -> &'a LanguageSettings {
1389        let language = self.language_at(point, cx);
1390        language_settings(language.map(|l| l.name()).as_deref(), cx)
1391    }
1392
1393    pub fn for_each_buffer(&self, mut f: impl FnMut(&ModelHandle<Buffer>)) {
1394        self.buffers
1395            .borrow()
1396            .values()
1397            .for_each(|state| f(&state.buffer))
1398    }
1399
1400    pub fn title<'a>(&'a self, cx: &'a AppContext) -> Cow<'a, str> {
1401        if let Some(title) = self.title.as_ref() {
1402            return title.into();
1403        }
1404
1405        if let Some(buffer) = self.as_singleton() {
1406            if let Some(file) = buffer.read(cx).file() {
1407                return file.file_name(cx).to_string_lossy();
1408            }
1409        }
1410
1411        "untitled".into()
1412    }
1413
1414    #[cfg(test)]
1415    pub fn is_parsing(&self, cx: &AppContext) -> bool {
1416        self.as_singleton().unwrap().read(cx).is_parsing()
1417    }
1418
1419    fn sync(&self, cx: &AppContext) {
1420        let mut snapshot = self.snapshot.borrow_mut();
1421        let mut excerpts_to_edit = Vec::new();
1422        let mut reparsed = false;
1423        let mut diagnostics_updated = false;
1424        let mut git_diff_updated = false;
1425        let mut is_dirty = false;
1426        let mut has_conflict = false;
1427        let mut edited = false;
1428        let mut buffers = self.buffers.borrow_mut();
1429        for buffer_state in buffers.values_mut() {
1430            let buffer = buffer_state.buffer.read(cx);
1431            let version = buffer.version();
1432            let parse_count = buffer.parse_count();
1433            let selections_update_count = buffer.selections_update_count();
1434            let diagnostics_update_count = buffer.diagnostics_update_count();
1435            let file_update_count = buffer.file_update_count();
1436            let git_diff_update_count = buffer.git_diff_update_count();
1437
1438            let buffer_edited = version.changed_since(&buffer_state.last_version);
1439            let buffer_reparsed = parse_count > buffer_state.last_parse_count;
1440            let buffer_selections_updated =
1441                selections_update_count > buffer_state.last_selections_update_count;
1442            let buffer_diagnostics_updated =
1443                diagnostics_update_count > buffer_state.last_diagnostics_update_count;
1444            let buffer_file_updated = file_update_count > buffer_state.last_file_update_count;
1445            let buffer_git_diff_updated =
1446                git_diff_update_count > buffer_state.last_git_diff_update_count;
1447            if buffer_edited
1448                || buffer_reparsed
1449                || buffer_selections_updated
1450                || buffer_diagnostics_updated
1451                || buffer_file_updated
1452                || buffer_git_diff_updated
1453            {
1454                buffer_state.last_version = version;
1455                buffer_state.last_parse_count = parse_count;
1456                buffer_state.last_selections_update_count = selections_update_count;
1457                buffer_state.last_diagnostics_update_count = diagnostics_update_count;
1458                buffer_state.last_file_update_count = file_update_count;
1459                buffer_state.last_git_diff_update_count = git_diff_update_count;
1460                excerpts_to_edit.extend(
1461                    buffer_state
1462                        .excerpts
1463                        .iter()
1464                        .map(|locator| (locator, buffer_state.buffer.clone(), buffer_edited)),
1465                );
1466            }
1467
1468            edited |= buffer_edited;
1469            reparsed |= buffer_reparsed;
1470            diagnostics_updated |= buffer_diagnostics_updated;
1471            git_diff_updated |= buffer_git_diff_updated;
1472            is_dirty |= buffer.is_dirty();
1473            has_conflict |= buffer.has_conflict();
1474        }
1475        if edited {
1476            snapshot.edit_count += 1;
1477        }
1478        if reparsed {
1479            snapshot.parse_count += 1;
1480        }
1481        if diagnostics_updated {
1482            snapshot.diagnostics_update_count += 1;
1483        }
1484        if git_diff_updated {
1485            snapshot.git_diff_update_count += 1;
1486        }
1487        snapshot.is_dirty = is_dirty;
1488        snapshot.has_conflict = has_conflict;
1489
1490        excerpts_to_edit.sort_unstable_by_key(|(locator, _, _)| *locator);
1491
1492        let mut edits = Vec::new();
1493        let mut new_excerpts = SumTree::new();
1494        let mut cursor = snapshot.excerpts.cursor::<(Option<&Locator>, usize)>();
1495
1496        for (locator, buffer, buffer_edited) in excerpts_to_edit {
1497            new_excerpts.push_tree(cursor.slice(&Some(locator), Bias::Left, &()), &());
1498            let old_excerpt = cursor.item().unwrap();
1499            let buffer = buffer.read(cx);
1500            let buffer_id = buffer.remote_id();
1501
1502            let mut new_excerpt;
1503            if buffer_edited {
1504                edits.extend(
1505                    buffer
1506                        .edits_since_in_range::<usize>(
1507                            old_excerpt.buffer.version(),
1508                            old_excerpt.range.context.clone(),
1509                        )
1510                        .map(|mut edit| {
1511                            let excerpt_old_start = cursor.start().1;
1512                            let excerpt_new_start = new_excerpts.summary().text.len;
1513                            edit.old.start += excerpt_old_start;
1514                            edit.old.end += excerpt_old_start;
1515                            edit.new.start += excerpt_new_start;
1516                            edit.new.end += excerpt_new_start;
1517                            edit
1518                        }),
1519                );
1520
1521                new_excerpt = Excerpt::new(
1522                    old_excerpt.id,
1523                    locator.clone(),
1524                    buffer_id,
1525                    buffer.snapshot(),
1526                    old_excerpt.range.clone(),
1527                    old_excerpt.has_trailing_newline,
1528                );
1529            } else {
1530                new_excerpt = old_excerpt.clone();
1531                new_excerpt.buffer = buffer.snapshot();
1532            }
1533
1534            new_excerpts.push(new_excerpt, &());
1535            cursor.next(&());
1536        }
1537        new_excerpts.push_tree(cursor.suffix(&()), &());
1538
1539        drop(cursor);
1540        snapshot.excerpts = new_excerpts;
1541
1542        self.subscriptions.publish(edits);
1543    }
1544}
1545
1546#[cfg(any(test, feature = "test-support"))]
1547impl MultiBuffer {
1548    pub fn build_simple(text: &str, cx: &mut gpui::AppContext) -> ModelHandle<Self> {
1549        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx));
1550        cx.add_model(|cx| Self::singleton(buffer, cx))
1551    }
1552
1553    pub fn build_random(rng: &mut impl rand::Rng, cx: &mut gpui::AppContext) -> ModelHandle<Self> {
1554        cx.add_model(|cx| {
1555            let mut multibuffer = MultiBuffer::new(0);
1556            let mutation_count = rng.gen_range(1..=5);
1557            multibuffer.randomly_edit_excerpts(rng, mutation_count, cx);
1558            multibuffer
1559        })
1560    }
1561
1562    pub fn randomly_edit(
1563        &mut self,
1564        rng: &mut impl rand::Rng,
1565        edit_count: usize,
1566        cx: &mut ModelContext<Self>,
1567    ) {
1568        use util::RandomCharIter;
1569
1570        let snapshot = self.read(cx);
1571        let mut edits: Vec<(Range<usize>, Arc<str>)> = Vec::new();
1572        let mut last_end = None;
1573        for _ in 0..edit_count {
1574            if last_end.map_or(false, |last_end| last_end >= snapshot.len()) {
1575                break;
1576            }
1577
1578            let new_start = last_end.map_or(0, |last_end| last_end + 1);
1579            let end = snapshot.clip_offset(rng.gen_range(new_start..=snapshot.len()), Bias::Right);
1580            let start = snapshot.clip_offset(rng.gen_range(new_start..=end), Bias::Right);
1581            last_end = Some(end);
1582
1583            let mut range = start..end;
1584            if rng.gen_bool(0.2) {
1585                mem::swap(&mut range.start, &mut range.end);
1586            }
1587
1588            let new_text_len = rng.gen_range(0..10);
1589            let new_text: String = RandomCharIter::new(&mut *rng).take(new_text_len).collect();
1590
1591            edits.push((range, new_text.into()));
1592        }
1593        log::info!("mutating multi-buffer with {:?}", edits);
1594        drop(snapshot);
1595
1596        self.edit(edits, None, cx);
1597    }
1598
1599    pub fn randomly_edit_excerpts(
1600        &mut self,
1601        rng: &mut impl rand::Rng,
1602        mutation_count: usize,
1603        cx: &mut ModelContext<Self>,
1604    ) {
1605        use rand::prelude::*;
1606        use std::env;
1607        use util::RandomCharIter;
1608
1609        let max_excerpts = env::var("MAX_EXCERPTS")
1610            .map(|i| i.parse().expect("invalid `MAX_EXCERPTS` variable"))
1611            .unwrap_or(5);
1612
1613        let mut buffers = Vec::new();
1614        for _ in 0..mutation_count {
1615            if rng.gen_bool(0.05) {
1616                log::info!("Clearing multi-buffer");
1617                self.clear(cx);
1618                continue;
1619            }
1620
1621            let excerpt_ids = self.excerpt_ids();
1622            if excerpt_ids.is_empty() || (rng.gen() && excerpt_ids.len() < max_excerpts) {
1623                let buffer_handle = if rng.gen() || self.buffers.borrow().is_empty() {
1624                    let text = RandomCharIter::new(&mut *rng).take(10).collect::<String>();
1625                    buffers.push(cx.add_model(|cx| Buffer::new(0, text, cx)));
1626                    let buffer = buffers.last().unwrap().read(cx);
1627                    log::info!(
1628                        "Creating new buffer {} with text: {:?}",
1629                        buffer.remote_id(),
1630                        buffer.text()
1631                    );
1632                    buffers.last().unwrap().clone()
1633                } else {
1634                    self.buffers
1635                        .borrow()
1636                        .values()
1637                        .choose(rng)
1638                        .unwrap()
1639                        .buffer
1640                        .clone()
1641                };
1642
1643                let buffer = buffer_handle.read(cx);
1644                let buffer_text = buffer.text();
1645                let ranges = (0..rng.gen_range(0..5))
1646                    .map(|_| {
1647                        let end_ix =
1648                            buffer.clip_offset(rng.gen_range(0..=buffer.len()), Bias::Right);
1649                        let start_ix = buffer.clip_offset(rng.gen_range(0..=end_ix), Bias::Left);
1650                        ExcerptRange {
1651                            context: start_ix..end_ix,
1652                            primary: None,
1653                        }
1654                    })
1655                    .collect::<Vec<_>>();
1656                log::info!(
1657                    "Inserting excerpts from buffer {} and ranges {:?}: {:?}",
1658                    buffer_handle.read(cx).remote_id(),
1659                    ranges.iter().map(|r| &r.context).collect::<Vec<_>>(),
1660                    ranges
1661                        .iter()
1662                        .map(|r| &buffer_text[r.context.clone()])
1663                        .collect::<Vec<_>>()
1664                );
1665
1666                let excerpt_id = self.push_excerpts(buffer_handle.clone(), ranges, cx);
1667                log::info!("Inserted with ids: {:?}", excerpt_id);
1668            } else {
1669                let remove_count = rng.gen_range(1..=excerpt_ids.len());
1670                let mut excerpts_to_remove = excerpt_ids
1671                    .choose_multiple(rng, remove_count)
1672                    .cloned()
1673                    .collect::<Vec<_>>();
1674                let snapshot = self.snapshot.borrow();
1675                excerpts_to_remove.sort_unstable_by(|a, b| a.cmp(b, &*snapshot));
1676                drop(snapshot);
1677                log::info!("Removing excerpts {:?}", excerpts_to_remove);
1678                self.remove_excerpts(excerpts_to_remove, cx);
1679            }
1680        }
1681    }
1682
1683    pub fn randomly_mutate(
1684        &mut self,
1685        rng: &mut impl rand::Rng,
1686        mutation_count: usize,
1687        cx: &mut ModelContext<Self>,
1688    ) {
1689        use rand::prelude::*;
1690
1691        if rng.gen_bool(0.7) || self.singleton {
1692            let buffer = self
1693                .buffers
1694                .borrow()
1695                .values()
1696                .choose(rng)
1697                .map(|state| state.buffer.clone());
1698
1699            if let Some(buffer) = buffer {
1700                buffer.update(cx, |buffer, cx| {
1701                    if rng.gen() {
1702                        buffer.randomly_edit(rng, mutation_count, cx);
1703                    } else {
1704                        buffer.randomly_undo_redo(rng, cx);
1705                    }
1706                });
1707            } else {
1708                self.randomly_edit(rng, mutation_count, cx);
1709            }
1710        } else {
1711            self.randomly_edit_excerpts(rng, mutation_count, cx);
1712        }
1713
1714        self.check_invariants(cx);
1715    }
1716
1717    fn check_invariants(&self, cx: &mut ModelContext<Self>) {
1718        let snapshot = self.read(cx);
1719        let excerpts = snapshot.excerpts.items(&());
1720        let excerpt_ids = snapshot.excerpt_ids.items(&());
1721
1722        for (ix, excerpt) in excerpts.iter().enumerate() {
1723            if ix == 0 {
1724                if excerpt.locator <= Locator::min() {
1725                    panic!("invalid first excerpt locator {:?}", excerpt.locator);
1726                }
1727            } else {
1728                if excerpt.locator <= excerpts[ix - 1].locator {
1729                    panic!("excerpts are out-of-order: {:?}", excerpts);
1730                }
1731            }
1732        }
1733
1734        for (ix, entry) in excerpt_ids.iter().enumerate() {
1735            if ix == 0 {
1736                if entry.id.cmp(&ExcerptId::min(), &*snapshot).is_le() {
1737                    panic!("invalid first excerpt id {:?}", entry.id);
1738                }
1739            } else {
1740                if entry.id <= excerpt_ids[ix - 1].id {
1741                    panic!("excerpt ids are out-of-order: {:?}", excerpt_ids);
1742                }
1743            }
1744        }
1745    }
1746}
1747
1748impl Entity for MultiBuffer {
1749    type Event = Event;
1750}
1751
1752impl MultiBufferSnapshot {
1753    pub fn text(&self) -> String {
1754        self.chunks(0..self.len(), false)
1755            .map(|chunk| chunk.text)
1756            .collect()
1757    }
1758
1759    pub fn reversed_chars_at<T: ToOffset>(&self, position: T) -> impl Iterator<Item = char> + '_ {
1760        let mut offset = position.to_offset(self);
1761        let mut cursor = self.excerpts.cursor::<usize>();
1762        cursor.seek(&offset, Bias::Left, &());
1763        let mut excerpt_chunks = cursor.item().map(|excerpt| {
1764            let end_before_footer = cursor.start() + excerpt.text_summary.len;
1765            let start = excerpt.range.context.start.to_offset(&excerpt.buffer);
1766            let end = start + (cmp::min(offset, end_before_footer) - cursor.start());
1767            excerpt.buffer.reversed_chunks_in_range(start..end)
1768        });
1769        iter::from_fn(move || {
1770            if offset == *cursor.start() {
1771                cursor.prev(&());
1772                let excerpt = cursor.item()?;
1773                excerpt_chunks = Some(
1774                    excerpt
1775                        .buffer
1776                        .reversed_chunks_in_range(excerpt.range.context.clone()),
1777                );
1778            }
1779
1780            let excerpt = cursor.item().unwrap();
1781            if offset == cursor.end(&()) && excerpt.has_trailing_newline {
1782                offset -= 1;
1783                Some("\n")
1784            } else {
1785                let chunk = excerpt_chunks.as_mut().unwrap().next().unwrap();
1786                offset -= chunk.len();
1787                Some(chunk)
1788            }
1789        })
1790        .flat_map(|c| c.chars().rev())
1791    }
1792
1793    pub fn chars_at<T: ToOffset>(&self, position: T) -> impl Iterator<Item = char> + '_ {
1794        let offset = position.to_offset(self);
1795        self.text_for_range(offset..self.len())
1796            .flat_map(|chunk| chunk.chars())
1797    }
1798
1799    pub fn text_for_range<T: ToOffset>(&self, range: Range<T>) -> impl Iterator<Item = &str> + '_ {
1800        self.chunks(range, false).map(|chunk| chunk.text)
1801    }
1802
1803    pub fn is_line_blank(&self, row: u32) -> bool {
1804        self.text_for_range(Point::new(row, 0)..Point::new(row, self.line_len(row)))
1805            .all(|chunk| chunk.matches(|c: char| !c.is_whitespace()).next().is_none())
1806    }
1807
1808    pub fn contains_str_at<T>(&self, position: T, needle: &str) -> bool
1809    where
1810        T: ToOffset,
1811    {
1812        let position = position.to_offset(self);
1813        position == self.clip_offset(position, Bias::Left)
1814            && self
1815                .bytes_in_range(position..self.len())
1816                .flatten()
1817                .copied()
1818                .take(needle.len())
1819                .eq(needle.bytes())
1820    }
1821
1822    pub fn surrounding_word<T: ToOffset>(&self, start: T) -> (Range<usize>, Option<CharKind>) {
1823        let mut start = start.to_offset(self);
1824        let mut end = start;
1825        let mut next_chars = self.chars_at(start).peekable();
1826        let mut prev_chars = self.reversed_chars_at(start).peekable();
1827        let word_kind = cmp::max(
1828            prev_chars.peek().copied().map(char_kind),
1829            next_chars.peek().copied().map(char_kind),
1830        );
1831
1832        for ch in prev_chars {
1833            if Some(char_kind(ch)) == word_kind && ch != '\n' {
1834                start -= ch.len_utf8();
1835            } else {
1836                break;
1837            }
1838        }
1839
1840        for ch in next_chars {
1841            if Some(char_kind(ch)) == word_kind && ch != '\n' {
1842                end += ch.len_utf8();
1843            } else {
1844                break;
1845            }
1846        }
1847
1848        (start..end, word_kind)
1849    }
1850
1851    pub fn as_singleton(&self) -> Option<(&ExcerptId, u64, &BufferSnapshot)> {
1852        if self.singleton {
1853            self.excerpts
1854                .iter()
1855                .next()
1856                .map(|e| (&e.id, e.buffer_id, &e.buffer))
1857        } else {
1858            None
1859        }
1860    }
1861
1862    pub fn len(&self) -> usize {
1863        self.excerpts.summary().text.len
1864    }
1865
1866    pub fn is_empty(&self) -> bool {
1867        self.excerpts.summary().text.len == 0
1868    }
1869
1870    pub fn max_buffer_row(&self) -> u32 {
1871        self.excerpts.summary().max_buffer_row
1872    }
1873
1874    pub fn clip_offset(&self, offset: usize, bias: Bias) -> usize {
1875        if let Some((_, _, buffer)) = self.as_singleton() {
1876            return buffer.clip_offset(offset, bias);
1877        }
1878
1879        let mut cursor = self.excerpts.cursor::<usize>();
1880        cursor.seek(&offset, Bias::Right, &());
1881        let overshoot = if let Some(excerpt) = cursor.item() {
1882            let excerpt_start = excerpt.range.context.start.to_offset(&excerpt.buffer);
1883            let buffer_offset = excerpt
1884                .buffer
1885                .clip_offset(excerpt_start + (offset - cursor.start()), bias);
1886            buffer_offset.saturating_sub(excerpt_start)
1887        } else {
1888            0
1889        };
1890        cursor.start() + overshoot
1891    }
1892
1893    pub fn clip_point(&self, point: Point, bias: Bias) -> Point {
1894        if let Some((_, _, buffer)) = self.as_singleton() {
1895            return buffer.clip_point(point, bias);
1896        }
1897
1898        let mut cursor = self.excerpts.cursor::<Point>();
1899        cursor.seek(&point, Bias::Right, &());
1900        let overshoot = if let Some(excerpt) = cursor.item() {
1901            let excerpt_start = excerpt.range.context.start.to_point(&excerpt.buffer);
1902            let buffer_point = excerpt
1903                .buffer
1904                .clip_point(excerpt_start + (point - cursor.start()), bias);
1905            buffer_point.saturating_sub(excerpt_start)
1906        } else {
1907            Point::zero()
1908        };
1909        *cursor.start() + overshoot
1910    }
1911
1912    pub fn clip_offset_utf16(&self, offset: OffsetUtf16, bias: Bias) -> OffsetUtf16 {
1913        if let Some((_, _, buffer)) = self.as_singleton() {
1914            return buffer.clip_offset_utf16(offset, bias);
1915        }
1916
1917        let mut cursor = self.excerpts.cursor::<OffsetUtf16>();
1918        cursor.seek(&offset, Bias::Right, &());
1919        let overshoot = if let Some(excerpt) = cursor.item() {
1920            let excerpt_start = excerpt.range.context.start.to_offset_utf16(&excerpt.buffer);
1921            let buffer_offset = excerpt
1922                .buffer
1923                .clip_offset_utf16(excerpt_start + (offset - cursor.start()), bias);
1924            OffsetUtf16(buffer_offset.0.saturating_sub(excerpt_start.0))
1925        } else {
1926            OffsetUtf16(0)
1927        };
1928        *cursor.start() + overshoot
1929    }
1930
1931    pub fn clip_point_utf16(&self, point: Unclipped<PointUtf16>, bias: Bias) -> PointUtf16 {
1932        if let Some((_, _, buffer)) = self.as_singleton() {
1933            return buffer.clip_point_utf16(point, bias);
1934        }
1935
1936        let mut cursor = self.excerpts.cursor::<PointUtf16>();
1937        cursor.seek(&point.0, Bias::Right, &());
1938        let overshoot = if let Some(excerpt) = cursor.item() {
1939            let excerpt_start = excerpt
1940                .buffer
1941                .offset_to_point_utf16(excerpt.range.context.start.to_offset(&excerpt.buffer));
1942            let buffer_point = excerpt
1943                .buffer
1944                .clip_point_utf16(Unclipped(excerpt_start + (point.0 - cursor.start())), bias);
1945            buffer_point.saturating_sub(excerpt_start)
1946        } else {
1947            PointUtf16::zero()
1948        };
1949        *cursor.start() + overshoot
1950    }
1951
1952    pub fn bytes_in_range<T: ToOffset>(&self, range: Range<T>) -> MultiBufferBytes {
1953        let range = range.start.to_offset(self)..range.end.to_offset(self);
1954        let mut excerpts = self.excerpts.cursor::<usize>();
1955        excerpts.seek(&range.start, Bias::Right, &());
1956
1957        let mut chunk = &[][..];
1958        let excerpt_bytes = if let Some(excerpt) = excerpts.item() {
1959            let mut excerpt_bytes = excerpt
1960                .bytes_in_range(range.start - excerpts.start()..range.end - excerpts.start());
1961            chunk = excerpt_bytes.next().unwrap_or(&[][..]);
1962            Some(excerpt_bytes)
1963        } else {
1964            None
1965        };
1966
1967        MultiBufferBytes {
1968            range,
1969            excerpts,
1970            excerpt_bytes,
1971            chunk,
1972        }
1973    }
1974
1975    pub fn buffer_rows(&self, start_row: u32) -> MultiBufferRows {
1976        let mut result = MultiBufferRows {
1977            buffer_row_range: 0..0,
1978            excerpts: self.excerpts.cursor(),
1979        };
1980        result.seek(start_row);
1981        result
1982    }
1983
1984    pub fn chunks<T: ToOffset>(&self, range: Range<T>, language_aware: bool) -> MultiBufferChunks {
1985        let range = range.start.to_offset(self)..range.end.to_offset(self);
1986        let mut chunks = MultiBufferChunks {
1987            range: range.clone(),
1988            excerpts: self.excerpts.cursor(),
1989            excerpt_chunks: None,
1990            language_aware,
1991        };
1992        chunks.seek(range.start);
1993        chunks
1994    }
1995
1996    pub fn offset_to_point(&self, offset: usize) -> Point {
1997        if let Some((_, _, buffer)) = self.as_singleton() {
1998            return buffer.offset_to_point(offset);
1999        }
2000
2001        let mut cursor = self.excerpts.cursor::<(usize, Point)>();
2002        cursor.seek(&offset, Bias::Right, &());
2003        if let Some(excerpt) = cursor.item() {
2004            let (start_offset, start_point) = cursor.start();
2005            let overshoot = offset - start_offset;
2006            let excerpt_start_offset = excerpt.range.context.start.to_offset(&excerpt.buffer);
2007            let excerpt_start_point = excerpt.range.context.start.to_point(&excerpt.buffer);
2008            let buffer_point = excerpt
2009                .buffer
2010                .offset_to_point(excerpt_start_offset + overshoot);
2011            *start_point + (buffer_point - excerpt_start_point)
2012        } else {
2013            self.excerpts.summary().text.lines
2014        }
2015    }
2016
2017    pub fn offset_to_point_utf16(&self, offset: usize) -> PointUtf16 {
2018        if let Some((_, _, buffer)) = self.as_singleton() {
2019            return buffer.offset_to_point_utf16(offset);
2020        }
2021
2022        let mut cursor = self.excerpts.cursor::<(usize, PointUtf16)>();
2023        cursor.seek(&offset, Bias::Right, &());
2024        if let Some(excerpt) = cursor.item() {
2025            let (start_offset, start_point) = cursor.start();
2026            let overshoot = offset - start_offset;
2027            let excerpt_start_offset = excerpt.range.context.start.to_offset(&excerpt.buffer);
2028            let excerpt_start_point = excerpt.range.context.start.to_point_utf16(&excerpt.buffer);
2029            let buffer_point = excerpt
2030                .buffer
2031                .offset_to_point_utf16(excerpt_start_offset + overshoot);
2032            *start_point + (buffer_point - excerpt_start_point)
2033        } else {
2034            self.excerpts.summary().text.lines_utf16()
2035        }
2036    }
2037
2038    pub fn point_to_point_utf16(&self, point: Point) -> PointUtf16 {
2039        if let Some((_, _, buffer)) = self.as_singleton() {
2040            return buffer.point_to_point_utf16(point);
2041        }
2042
2043        let mut cursor = self.excerpts.cursor::<(Point, PointUtf16)>();
2044        cursor.seek(&point, Bias::Right, &());
2045        if let Some(excerpt) = cursor.item() {
2046            let (start_offset, start_point) = cursor.start();
2047            let overshoot = point - start_offset;
2048            let excerpt_start_point = excerpt.range.context.start.to_point(&excerpt.buffer);
2049            let excerpt_start_point_utf16 =
2050                excerpt.range.context.start.to_point_utf16(&excerpt.buffer);
2051            let buffer_point = excerpt
2052                .buffer
2053                .point_to_point_utf16(excerpt_start_point + overshoot);
2054            *start_point + (buffer_point - excerpt_start_point_utf16)
2055        } else {
2056            self.excerpts.summary().text.lines_utf16()
2057        }
2058    }
2059
2060    pub fn point_to_offset(&self, point: Point) -> usize {
2061        if let Some((_, _, buffer)) = self.as_singleton() {
2062            return buffer.point_to_offset(point);
2063        }
2064
2065        let mut cursor = self.excerpts.cursor::<(Point, usize)>();
2066        cursor.seek(&point, Bias::Right, &());
2067        if let Some(excerpt) = cursor.item() {
2068            let (start_point, start_offset) = cursor.start();
2069            let overshoot = point - start_point;
2070            let excerpt_start_offset = excerpt.range.context.start.to_offset(&excerpt.buffer);
2071            let excerpt_start_point = excerpt.range.context.start.to_point(&excerpt.buffer);
2072            let buffer_offset = excerpt
2073                .buffer
2074                .point_to_offset(excerpt_start_point + overshoot);
2075            *start_offset + buffer_offset - excerpt_start_offset
2076        } else {
2077            self.excerpts.summary().text.len
2078        }
2079    }
2080
2081    pub fn offset_utf16_to_offset(&self, offset_utf16: OffsetUtf16) -> usize {
2082        if let Some((_, _, buffer)) = self.as_singleton() {
2083            return buffer.offset_utf16_to_offset(offset_utf16);
2084        }
2085
2086        let mut cursor = self.excerpts.cursor::<(OffsetUtf16, usize)>();
2087        cursor.seek(&offset_utf16, Bias::Right, &());
2088        if let Some(excerpt) = cursor.item() {
2089            let (start_offset_utf16, start_offset) = cursor.start();
2090            let overshoot = offset_utf16 - start_offset_utf16;
2091            let excerpt_start_offset = excerpt.range.context.start.to_offset(&excerpt.buffer);
2092            let excerpt_start_offset_utf16 =
2093                excerpt.buffer.offset_to_offset_utf16(excerpt_start_offset);
2094            let buffer_offset = excerpt
2095                .buffer
2096                .offset_utf16_to_offset(excerpt_start_offset_utf16 + overshoot);
2097            *start_offset + (buffer_offset - excerpt_start_offset)
2098        } else {
2099            self.excerpts.summary().text.len
2100        }
2101    }
2102
2103    pub fn offset_to_offset_utf16(&self, offset: usize) -> OffsetUtf16 {
2104        if let Some((_, _, buffer)) = self.as_singleton() {
2105            return buffer.offset_to_offset_utf16(offset);
2106        }
2107
2108        let mut cursor = self.excerpts.cursor::<(usize, OffsetUtf16)>();
2109        cursor.seek(&offset, Bias::Right, &());
2110        if let Some(excerpt) = cursor.item() {
2111            let (start_offset, start_offset_utf16) = cursor.start();
2112            let overshoot = offset - start_offset;
2113            let excerpt_start_offset_utf16 =
2114                excerpt.range.context.start.to_offset_utf16(&excerpt.buffer);
2115            let excerpt_start_offset = excerpt
2116                .buffer
2117                .offset_utf16_to_offset(excerpt_start_offset_utf16);
2118            let buffer_offset_utf16 = excerpt
2119                .buffer
2120                .offset_to_offset_utf16(excerpt_start_offset + overshoot);
2121            *start_offset_utf16 + (buffer_offset_utf16 - excerpt_start_offset_utf16)
2122        } else {
2123            self.excerpts.summary().text.len_utf16
2124        }
2125    }
2126
2127    pub fn point_utf16_to_offset(&self, point: PointUtf16) -> usize {
2128        if let Some((_, _, buffer)) = self.as_singleton() {
2129            return buffer.point_utf16_to_offset(point);
2130        }
2131
2132        let mut cursor = self.excerpts.cursor::<(PointUtf16, usize)>();
2133        cursor.seek(&point, Bias::Right, &());
2134        if let Some(excerpt) = cursor.item() {
2135            let (start_point, start_offset) = cursor.start();
2136            let overshoot = point - start_point;
2137            let excerpt_start_offset = excerpt.range.context.start.to_offset(&excerpt.buffer);
2138            let excerpt_start_point = excerpt
2139                .buffer
2140                .offset_to_point_utf16(excerpt.range.context.start.to_offset(&excerpt.buffer));
2141            let buffer_offset = excerpt
2142                .buffer
2143                .point_utf16_to_offset(excerpt_start_point + overshoot);
2144            *start_offset + (buffer_offset - excerpt_start_offset)
2145        } else {
2146            self.excerpts.summary().text.len
2147        }
2148    }
2149
2150    pub fn point_to_buffer_offset<T: ToOffset>(
2151        &self,
2152        point: T,
2153    ) -> Option<(&BufferSnapshot, usize)> {
2154        let offset = point.to_offset(&self);
2155        let mut cursor = self.excerpts.cursor::<usize>();
2156        cursor.seek(&offset, Bias::Right, &());
2157        if cursor.item().is_none() {
2158            cursor.prev(&());
2159        }
2160
2161        cursor.item().map(|excerpt| {
2162            let excerpt_start = excerpt.range.context.start.to_offset(&excerpt.buffer);
2163            let buffer_point = excerpt_start + offset - *cursor.start();
2164            (&excerpt.buffer, buffer_point)
2165        })
2166    }
2167
2168    pub fn suggested_indents(
2169        &self,
2170        rows: impl IntoIterator<Item = u32>,
2171        cx: &AppContext,
2172    ) -> BTreeMap<u32, IndentSize> {
2173        let mut result = BTreeMap::new();
2174
2175        let mut rows_for_excerpt = Vec::new();
2176        let mut cursor = self.excerpts.cursor::<Point>();
2177        let mut rows = rows.into_iter().peekable();
2178        let mut prev_row = u32::MAX;
2179        let mut prev_language_indent_size = IndentSize::default();
2180
2181        while let Some(row) = rows.next() {
2182            cursor.seek(&Point::new(row, 0), Bias::Right, &());
2183            let excerpt = match cursor.item() {
2184                Some(excerpt) => excerpt,
2185                _ => continue,
2186            };
2187
2188            // Retrieve the language and indent size once for each disjoint region being indented.
2189            let single_indent_size = if row.saturating_sub(1) == prev_row {
2190                prev_language_indent_size
2191            } else {
2192                excerpt
2193                    .buffer
2194                    .language_indent_size_at(Point::new(row, 0), cx)
2195            };
2196            prev_language_indent_size = single_indent_size;
2197            prev_row = row;
2198
2199            let start_buffer_row = excerpt.range.context.start.to_point(&excerpt.buffer).row;
2200            let start_multibuffer_row = cursor.start().row;
2201
2202            rows_for_excerpt.push(row);
2203            while let Some(next_row) = rows.peek().copied() {
2204                if cursor.end(&()).row > next_row {
2205                    rows_for_excerpt.push(next_row);
2206                    rows.next();
2207                } else {
2208                    break;
2209                }
2210            }
2211
2212            let buffer_rows = rows_for_excerpt
2213                .drain(..)
2214                .map(|row| start_buffer_row + row - start_multibuffer_row);
2215            let buffer_indents = excerpt
2216                .buffer
2217                .suggested_indents(buffer_rows, single_indent_size);
2218            let multibuffer_indents = buffer_indents
2219                .into_iter()
2220                .map(|(row, indent)| (start_multibuffer_row + row - start_buffer_row, indent));
2221            result.extend(multibuffer_indents);
2222        }
2223
2224        result
2225    }
2226
2227    pub fn indent_size_for_line(&self, row: u32) -> IndentSize {
2228        if let Some((buffer, range)) = self.buffer_line_for_row(row) {
2229            let mut size = buffer.indent_size_for_line(range.start.row);
2230            size.len = size
2231                .len
2232                .min(range.end.column)
2233                .saturating_sub(range.start.column);
2234            size
2235        } else {
2236            IndentSize::spaces(0)
2237        }
2238    }
2239
2240    pub fn line_len(&self, row: u32) -> u32 {
2241        if let Some((_, range)) = self.buffer_line_for_row(row) {
2242            range.end.column - range.start.column
2243        } else {
2244            0
2245        }
2246    }
2247
2248    pub fn buffer_line_for_row(&self, row: u32) -> Option<(&BufferSnapshot, Range<Point>)> {
2249        let mut cursor = self.excerpts.cursor::<Point>();
2250        let point = Point::new(row, 0);
2251        cursor.seek(&point, Bias::Right, &());
2252        if cursor.item().is_none() && *cursor.start() == point {
2253            cursor.prev(&());
2254        }
2255        if let Some(excerpt) = cursor.item() {
2256            let overshoot = row - cursor.start().row;
2257            let excerpt_start = excerpt.range.context.start.to_point(&excerpt.buffer);
2258            let excerpt_end = excerpt.range.context.end.to_point(&excerpt.buffer);
2259            let buffer_row = excerpt_start.row + overshoot;
2260            let line_start = Point::new(buffer_row, 0);
2261            let line_end = Point::new(buffer_row, excerpt.buffer.line_len(buffer_row));
2262            return Some((
2263                &excerpt.buffer,
2264                line_start.max(excerpt_start)..line_end.min(excerpt_end),
2265            ));
2266        }
2267        None
2268    }
2269
2270    pub fn max_point(&self) -> Point {
2271        self.text_summary().lines
2272    }
2273
2274    pub fn text_summary(&self) -> TextSummary {
2275        self.excerpts.summary().text.clone()
2276    }
2277
2278    pub fn text_summary_for_range<D, O>(&self, range: Range<O>) -> D
2279    where
2280        D: TextDimension,
2281        O: ToOffset,
2282    {
2283        let mut summary = D::default();
2284        let mut range = range.start.to_offset(self)..range.end.to_offset(self);
2285        let mut cursor = self.excerpts.cursor::<usize>();
2286        cursor.seek(&range.start, Bias::Right, &());
2287        if let Some(excerpt) = cursor.item() {
2288            let mut end_before_newline = cursor.end(&());
2289            if excerpt.has_trailing_newline {
2290                end_before_newline -= 1;
2291            }
2292
2293            let excerpt_start = excerpt.range.context.start.to_offset(&excerpt.buffer);
2294            let start_in_excerpt = excerpt_start + (range.start - cursor.start());
2295            let end_in_excerpt =
2296                excerpt_start + (cmp::min(end_before_newline, range.end) - cursor.start());
2297            summary.add_assign(
2298                &excerpt
2299                    .buffer
2300                    .text_summary_for_range(start_in_excerpt..end_in_excerpt),
2301            );
2302
2303            if range.end > end_before_newline {
2304                summary.add_assign(&D::from_text_summary(&TextSummary::from("\n")));
2305            }
2306
2307            cursor.next(&());
2308        }
2309
2310        if range.end > *cursor.start() {
2311            summary.add_assign(&D::from_text_summary(&cursor.summary::<_, TextSummary>(
2312                &range.end,
2313                Bias::Right,
2314                &(),
2315            )));
2316            if let Some(excerpt) = cursor.item() {
2317                range.end = cmp::max(*cursor.start(), range.end);
2318
2319                let excerpt_start = excerpt.range.context.start.to_offset(&excerpt.buffer);
2320                let end_in_excerpt = excerpt_start + (range.end - cursor.start());
2321                summary.add_assign(
2322                    &excerpt
2323                        .buffer
2324                        .text_summary_for_range(excerpt_start..end_in_excerpt),
2325                );
2326            }
2327        }
2328
2329        summary
2330    }
2331
2332    pub fn summary_for_anchor<D>(&self, anchor: &Anchor) -> D
2333    where
2334        D: TextDimension + Ord + Sub<D, Output = D>,
2335    {
2336        let mut cursor = self.excerpts.cursor::<ExcerptSummary>();
2337        let locator = self.excerpt_locator_for_id(anchor.excerpt_id);
2338
2339        cursor.seek(locator, Bias::Left, &());
2340        if cursor.item().is_none() {
2341            cursor.next(&());
2342        }
2343
2344        let mut position = D::from_text_summary(&cursor.start().text);
2345        if let Some(excerpt) = cursor.item() {
2346            if excerpt.id == anchor.excerpt_id {
2347                let excerpt_buffer_start =
2348                    excerpt.range.context.start.summary::<D>(&excerpt.buffer);
2349                let excerpt_buffer_end = excerpt.range.context.end.summary::<D>(&excerpt.buffer);
2350                let buffer_position = cmp::min(
2351                    excerpt_buffer_end,
2352                    anchor.text_anchor.summary::<D>(&excerpt.buffer),
2353                );
2354                if buffer_position > excerpt_buffer_start {
2355                    position.add_assign(&(buffer_position - excerpt_buffer_start));
2356                }
2357            }
2358        }
2359        position
2360    }
2361
2362    pub fn summaries_for_anchors<'a, D, I>(&'a self, anchors: I) -> Vec<D>
2363    where
2364        D: TextDimension + Ord + Sub<D, Output = D>,
2365        I: 'a + IntoIterator<Item = &'a Anchor>,
2366    {
2367        if let Some((_, _, buffer)) = self.as_singleton() {
2368            return buffer
2369                .summaries_for_anchors(anchors.into_iter().map(|a| &a.text_anchor))
2370                .collect();
2371        }
2372
2373        let mut anchors = anchors.into_iter().peekable();
2374        let mut cursor = self.excerpts.cursor::<ExcerptSummary>();
2375        let mut summaries = Vec::new();
2376        while let Some(anchor) = anchors.peek() {
2377            let excerpt_id = anchor.excerpt_id;
2378            let excerpt_anchors = iter::from_fn(|| {
2379                let anchor = anchors.peek()?;
2380                if anchor.excerpt_id == excerpt_id {
2381                    Some(&anchors.next().unwrap().text_anchor)
2382                } else {
2383                    None
2384                }
2385            });
2386
2387            let locator = self.excerpt_locator_for_id(excerpt_id);
2388            cursor.seek_forward(locator, Bias::Left, &());
2389            if cursor.item().is_none() {
2390                cursor.next(&());
2391            }
2392
2393            let position = D::from_text_summary(&cursor.start().text);
2394            if let Some(excerpt) = cursor.item() {
2395                if excerpt.id == excerpt_id {
2396                    let excerpt_buffer_start =
2397                        excerpt.range.context.start.summary::<D>(&excerpt.buffer);
2398                    let excerpt_buffer_end =
2399                        excerpt.range.context.end.summary::<D>(&excerpt.buffer);
2400                    summaries.extend(
2401                        excerpt
2402                            .buffer
2403                            .summaries_for_anchors::<D, _>(excerpt_anchors)
2404                            .map(move |summary| {
2405                                let summary = cmp::min(excerpt_buffer_end.clone(), summary);
2406                                let mut position = position.clone();
2407                                let excerpt_buffer_start = excerpt_buffer_start.clone();
2408                                if summary > excerpt_buffer_start {
2409                                    position.add_assign(&(summary - excerpt_buffer_start));
2410                                }
2411                                position
2412                            }),
2413                    );
2414                    continue;
2415                }
2416            }
2417
2418            summaries.extend(excerpt_anchors.map(|_| position.clone()));
2419        }
2420
2421        summaries
2422    }
2423
2424    pub fn refresh_anchors<'a, I>(&'a self, anchors: I) -> Vec<(usize, Anchor, bool)>
2425    where
2426        I: 'a + IntoIterator<Item = &'a Anchor>,
2427    {
2428        let mut anchors = anchors.into_iter().enumerate().peekable();
2429        let mut cursor = self.excerpts.cursor::<Option<&Locator>>();
2430        cursor.next(&());
2431
2432        let mut result = Vec::new();
2433
2434        while let Some((_, anchor)) = anchors.peek() {
2435            let old_excerpt_id = anchor.excerpt_id;
2436
2437            // Find the location where this anchor's excerpt should be.
2438            let old_locator = self.excerpt_locator_for_id(old_excerpt_id);
2439            cursor.seek_forward(&Some(old_locator), Bias::Left, &());
2440
2441            if cursor.item().is_none() {
2442                cursor.next(&());
2443            }
2444
2445            let next_excerpt = cursor.item();
2446            let prev_excerpt = cursor.prev_item();
2447
2448            // Process all of the anchors for this excerpt.
2449            while let Some((_, anchor)) = anchors.peek() {
2450                if anchor.excerpt_id != old_excerpt_id {
2451                    break;
2452                }
2453                let (anchor_ix, anchor) = anchors.next().unwrap();
2454                let mut anchor = *anchor;
2455
2456                // Leave min and max anchors unchanged if invalid or
2457                // if the old excerpt still exists at this location
2458                let mut kept_position = next_excerpt
2459                    .map_or(false, |e| e.id == old_excerpt_id && e.contains(&anchor))
2460                    || old_excerpt_id == ExcerptId::max()
2461                    || old_excerpt_id == ExcerptId::min();
2462
2463                // If the old excerpt no longer exists at this location, then attempt to
2464                // find an equivalent position for this anchor in an adjacent excerpt.
2465                if !kept_position {
2466                    for excerpt in [next_excerpt, prev_excerpt].iter().filter_map(|e| *e) {
2467                        if excerpt.contains(&anchor) {
2468                            anchor.excerpt_id = excerpt.id.clone();
2469                            kept_position = true;
2470                            break;
2471                        }
2472                    }
2473                }
2474
2475                // If there's no adjacent excerpt that contains the anchor's position,
2476                // then report that the anchor has lost its position.
2477                if !kept_position {
2478                    anchor = if let Some(excerpt) = next_excerpt {
2479                        let mut text_anchor = excerpt
2480                            .range
2481                            .context
2482                            .start
2483                            .bias(anchor.text_anchor.bias, &excerpt.buffer);
2484                        if text_anchor
2485                            .cmp(&excerpt.range.context.end, &excerpt.buffer)
2486                            .is_gt()
2487                        {
2488                            text_anchor = excerpt.range.context.end;
2489                        }
2490                        Anchor {
2491                            buffer_id: Some(excerpt.buffer_id),
2492                            excerpt_id: excerpt.id.clone(),
2493                            text_anchor,
2494                        }
2495                    } else if let Some(excerpt) = prev_excerpt {
2496                        let mut text_anchor = excerpt
2497                            .range
2498                            .context
2499                            .end
2500                            .bias(anchor.text_anchor.bias, &excerpt.buffer);
2501                        if text_anchor
2502                            .cmp(&excerpt.range.context.start, &excerpt.buffer)
2503                            .is_lt()
2504                        {
2505                            text_anchor = excerpt.range.context.start;
2506                        }
2507                        Anchor {
2508                            buffer_id: Some(excerpt.buffer_id),
2509                            excerpt_id: excerpt.id.clone(),
2510                            text_anchor,
2511                        }
2512                    } else if anchor.text_anchor.bias == Bias::Left {
2513                        Anchor::min()
2514                    } else {
2515                        Anchor::max()
2516                    };
2517                }
2518
2519                result.push((anchor_ix, anchor, kept_position));
2520            }
2521        }
2522        result.sort_unstable_by(|a, b| a.1.cmp(&b.1, self));
2523        result
2524    }
2525
2526    pub fn anchor_before<T: ToOffset>(&self, position: T) -> Anchor {
2527        self.anchor_at(position, Bias::Left)
2528    }
2529
2530    pub fn anchor_after<T: ToOffset>(&self, position: T) -> Anchor {
2531        self.anchor_at(position, Bias::Right)
2532    }
2533
2534    pub fn anchor_at<T: ToOffset>(&self, position: T, mut bias: Bias) -> Anchor {
2535        let offset = position.to_offset(self);
2536        if let Some((excerpt_id, buffer_id, buffer)) = self.as_singleton() {
2537            return Anchor {
2538                buffer_id: Some(buffer_id),
2539                excerpt_id: excerpt_id.clone(),
2540                text_anchor: buffer.anchor_at(offset, bias),
2541            };
2542        }
2543
2544        let mut cursor = self.excerpts.cursor::<(usize, Option<ExcerptId>)>();
2545        cursor.seek(&offset, Bias::Right, &());
2546        if cursor.item().is_none() && offset == cursor.start().0 && bias == Bias::Left {
2547            cursor.prev(&());
2548        }
2549        if let Some(excerpt) = cursor.item() {
2550            let mut overshoot = offset.saturating_sub(cursor.start().0);
2551            if excerpt.has_trailing_newline && offset == cursor.end(&()).0 {
2552                overshoot -= 1;
2553                bias = Bias::Right;
2554            }
2555
2556            let buffer_start = excerpt.range.context.start.to_offset(&excerpt.buffer);
2557            let text_anchor =
2558                excerpt.clip_anchor(excerpt.buffer.anchor_at(buffer_start + overshoot, bias));
2559            Anchor {
2560                buffer_id: Some(excerpt.buffer_id),
2561                excerpt_id: excerpt.id.clone(),
2562                text_anchor,
2563            }
2564        } else if offset == 0 && bias == Bias::Left {
2565            Anchor::min()
2566        } else {
2567            Anchor::max()
2568        }
2569    }
2570
2571    pub fn anchor_in_excerpt(&self, excerpt_id: ExcerptId, text_anchor: text::Anchor) -> Anchor {
2572        let locator = self.excerpt_locator_for_id(excerpt_id);
2573        let mut cursor = self.excerpts.cursor::<Option<&Locator>>();
2574        cursor.seek(locator, Bias::Left, &());
2575        if let Some(excerpt) = cursor.item() {
2576            if excerpt.id == excerpt_id {
2577                let text_anchor = excerpt.clip_anchor(text_anchor);
2578                drop(cursor);
2579                return Anchor {
2580                    buffer_id: Some(excerpt.buffer_id),
2581                    excerpt_id,
2582                    text_anchor,
2583                };
2584            }
2585        }
2586        panic!("excerpt not found");
2587    }
2588
2589    pub fn can_resolve(&self, anchor: &Anchor) -> bool {
2590        if anchor.excerpt_id == ExcerptId::min() || anchor.excerpt_id == ExcerptId::max() {
2591            true
2592        } else if let Some(excerpt) = self.excerpt(anchor.excerpt_id) {
2593            excerpt.buffer.can_resolve(&anchor.text_anchor)
2594        } else {
2595            false
2596        }
2597    }
2598
2599    pub fn excerpts(
2600        &self,
2601    ) -> impl Iterator<Item = (ExcerptId, &BufferSnapshot, ExcerptRange<text::Anchor>)> {
2602        self.excerpts
2603            .iter()
2604            .map(|excerpt| (excerpt.id, &excerpt.buffer, excerpt.range.clone()))
2605    }
2606
2607    pub fn excerpt_boundaries_in_range<R, T>(
2608        &self,
2609        range: R,
2610    ) -> impl Iterator<Item = ExcerptBoundary> + '_
2611    where
2612        R: RangeBounds<T>,
2613        T: ToOffset,
2614    {
2615        let start_offset;
2616        let start = match range.start_bound() {
2617            Bound::Included(start) => {
2618                start_offset = start.to_offset(self);
2619                Bound::Included(start_offset)
2620            }
2621            Bound::Excluded(start) => {
2622                start_offset = start.to_offset(self);
2623                Bound::Excluded(start_offset)
2624            }
2625            Bound::Unbounded => {
2626                start_offset = 0;
2627                Bound::Unbounded
2628            }
2629        };
2630        let end = match range.end_bound() {
2631            Bound::Included(end) => Bound::Included(end.to_offset(self)),
2632            Bound::Excluded(end) => Bound::Excluded(end.to_offset(self)),
2633            Bound::Unbounded => Bound::Unbounded,
2634        };
2635        let bounds = (start, end);
2636
2637        let mut cursor = self.excerpts.cursor::<(usize, Point)>();
2638        cursor.seek(&start_offset, Bias::Right, &());
2639        if cursor.item().is_none() {
2640            cursor.prev(&());
2641        }
2642        if !bounds.contains(&cursor.start().0) {
2643            cursor.next(&());
2644        }
2645
2646        let mut prev_buffer_id = cursor.prev_item().map(|excerpt| excerpt.buffer_id);
2647        std::iter::from_fn(move || {
2648            if self.singleton {
2649                None
2650            } else if bounds.contains(&cursor.start().0) {
2651                let excerpt = cursor.item()?;
2652                let starts_new_buffer = Some(excerpt.buffer_id) != prev_buffer_id;
2653                let boundary = ExcerptBoundary {
2654                    id: excerpt.id.clone(),
2655                    row: cursor.start().1.row,
2656                    buffer: excerpt.buffer.clone(),
2657                    range: excerpt.range.clone(),
2658                    starts_new_buffer,
2659                };
2660
2661                prev_buffer_id = Some(excerpt.buffer_id);
2662                cursor.next(&());
2663                Some(boundary)
2664            } else {
2665                None
2666            }
2667        })
2668    }
2669
2670    pub fn edit_count(&self) -> usize {
2671        self.edit_count
2672    }
2673
2674    pub fn parse_count(&self) -> usize {
2675        self.parse_count
2676    }
2677
2678    /// Returns the smallest enclosing bracket ranges containing the given range or
2679    /// None if no brackets contain range or the range is not contained in a single
2680    /// excerpt
2681    pub fn innermost_enclosing_bracket_ranges<T: ToOffset>(
2682        &self,
2683        range: Range<T>,
2684    ) -> Option<(Range<usize>, Range<usize>)> {
2685        let range = range.start.to_offset(self)..range.end.to_offset(self);
2686
2687        // Get the ranges of the innermost pair of brackets.
2688        let mut result: Option<(Range<usize>, Range<usize>)> = None;
2689
2690        let Some(enclosing_bracket_ranges) = self.enclosing_bracket_ranges(range.clone()) else { return None; };
2691
2692        for (open, close) in enclosing_bracket_ranges {
2693            let len = close.end - open.start;
2694
2695            if let Some((existing_open, existing_close)) = &result {
2696                let existing_len = existing_close.end - existing_open.start;
2697                if len > existing_len {
2698                    continue;
2699                }
2700            }
2701
2702            result = Some((open, close));
2703        }
2704
2705        result
2706    }
2707
2708    /// Returns enclosing bracket ranges containing the given range or returns None if the range is
2709    /// not contained in a single excerpt
2710    pub fn enclosing_bracket_ranges<'a, T: ToOffset>(
2711        &'a self,
2712        range: Range<T>,
2713    ) -> Option<impl Iterator<Item = (Range<usize>, Range<usize>)> + 'a> {
2714        let range = range.start.to_offset(self)..range.end.to_offset(self);
2715
2716        self.bracket_ranges(range.clone()).map(|range_pairs| {
2717            range_pairs
2718                .filter(move |(open, close)| open.start <= range.start && close.end >= range.end)
2719        })
2720    }
2721
2722    /// Returns bracket range pairs overlapping the given `range` or returns None if the `range` is
2723    /// not contained in a single excerpt
2724    pub fn bracket_ranges<'a, T: ToOffset>(
2725        &'a self,
2726        range: Range<T>,
2727    ) -> Option<impl Iterator<Item = (Range<usize>, Range<usize>)> + 'a> {
2728        let range = range.start.to_offset(self)..range.end.to_offset(self);
2729        let excerpt = self.excerpt_containing(range.clone());
2730        excerpt.map(|(excerpt, excerpt_offset)| {
2731            let excerpt_buffer_start = excerpt.range.context.start.to_offset(&excerpt.buffer);
2732            let excerpt_buffer_end = excerpt_buffer_start + excerpt.text_summary.len;
2733
2734            let start_in_buffer = excerpt_buffer_start + range.start.saturating_sub(excerpt_offset);
2735            let end_in_buffer = excerpt_buffer_start + range.end.saturating_sub(excerpt_offset);
2736
2737            excerpt
2738                .buffer
2739                .bracket_ranges(start_in_buffer..end_in_buffer)
2740                .filter_map(move |(start_bracket_range, end_bracket_range)| {
2741                    if start_bracket_range.start < excerpt_buffer_start
2742                        || end_bracket_range.end > excerpt_buffer_end
2743                    {
2744                        return None;
2745                    }
2746
2747                    let mut start_bracket_range = start_bracket_range.clone();
2748                    start_bracket_range.start =
2749                        excerpt_offset + (start_bracket_range.start - excerpt_buffer_start);
2750                    start_bracket_range.end =
2751                        excerpt_offset + (start_bracket_range.end - excerpt_buffer_start);
2752
2753                    let mut end_bracket_range = end_bracket_range.clone();
2754                    end_bracket_range.start =
2755                        excerpt_offset + (end_bracket_range.start - excerpt_buffer_start);
2756                    end_bracket_range.end =
2757                        excerpt_offset + (end_bracket_range.end - excerpt_buffer_start);
2758                    Some((start_bracket_range, end_bracket_range))
2759                })
2760        })
2761    }
2762
2763    pub fn diagnostics_update_count(&self) -> usize {
2764        self.diagnostics_update_count
2765    }
2766
2767    pub fn git_diff_update_count(&self) -> usize {
2768        self.git_diff_update_count
2769    }
2770
2771    pub fn trailing_excerpt_update_count(&self) -> usize {
2772        self.trailing_excerpt_update_count
2773    }
2774
2775    pub fn file_at<'a, T: ToOffset>(&'a self, point: T) -> Option<&'a Arc<dyn File>> {
2776        self.point_to_buffer_offset(point)
2777            .and_then(|(buffer, _)| buffer.file())
2778    }
2779
2780    pub fn language_at<'a, T: ToOffset>(&'a self, point: T) -> Option<&'a Arc<Language>> {
2781        self.point_to_buffer_offset(point)
2782            .and_then(|(buffer, offset)| buffer.language_at(offset))
2783    }
2784
2785    pub fn settings_at<'a, T: ToOffset>(
2786        &'a self,
2787        point: T,
2788        cx: &'a AppContext,
2789    ) -> &'a LanguageSettings {
2790        self.point_to_buffer_offset(point)
2791            .map(|(buffer, offset)| buffer.settings_at(offset, cx))
2792            .unwrap_or_else(|| language_settings(None, cx))
2793    }
2794
2795    pub fn language_scope_at<'a, T: ToOffset>(&'a self, point: T) -> Option<LanguageScope> {
2796        self.point_to_buffer_offset(point)
2797            .and_then(|(buffer, offset)| buffer.language_scope_at(offset))
2798    }
2799
2800    pub fn language_indent_size_at<T: ToOffset>(
2801        &self,
2802        position: T,
2803        cx: &AppContext,
2804    ) -> Option<IndentSize> {
2805        let (buffer_snapshot, offset) = self.point_to_buffer_offset(position)?;
2806        Some(buffer_snapshot.language_indent_size_at(offset, cx))
2807    }
2808
2809    pub fn is_dirty(&self) -> bool {
2810        self.is_dirty
2811    }
2812
2813    pub fn has_conflict(&self) -> bool {
2814        self.has_conflict
2815    }
2816
2817    pub fn diagnostic_group<'a, O>(
2818        &'a self,
2819        group_id: usize,
2820    ) -> impl Iterator<Item = DiagnosticEntry<O>> + 'a
2821    where
2822        O: text::FromAnchor + 'a,
2823    {
2824        self.as_singleton()
2825            .into_iter()
2826            .flat_map(move |(_, _, buffer)| buffer.diagnostic_group(group_id))
2827    }
2828
2829    pub fn diagnostics_in_range<'a, T, O>(
2830        &'a self,
2831        range: Range<T>,
2832        reversed: bool,
2833    ) -> impl Iterator<Item = DiagnosticEntry<O>> + 'a
2834    where
2835        T: 'a + ToOffset,
2836        O: 'a + text::FromAnchor + Ord,
2837    {
2838        self.as_singleton()
2839            .into_iter()
2840            .flat_map(move |(_, _, buffer)| {
2841                buffer.diagnostics_in_range(
2842                    range.start.to_offset(self)..range.end.to_offset(self),
2843                    reversed,
2844                )
2845            })
2846    }
2847
2848    pub fn has_git_diffs(&self) -> bool {
2849        for excerpt in self.excerpts.iter() {
2850            if !excerpt.buffer.git_diff.is_empty() {
2851                return true;
2852            }
2853        }
2854        false
2855    }
2856
2857    pub fn git_diff_hunks_in_range_rev<'a>(
2858        &'a self,
2859        row_range: Range<u32>,
2860    ) -> impl 'a + Iterator<Item = DiffHunk<u32>> {
2861        let mut cursor = self.excerpts.cursor::<Point>();
2862
2863        cursor.seek(&Point::new(row_range.end, 0), Bias::Left, &());
2864        if cursor.item().is_none() {
2865            cursor.prev(&());
2866        }
2867
2868        std::iter::from_fn(move || {
2869            let excerpt = cursor.item()?;
2870            let multibuffer_start = *cursor.start();
2871            let multibuffer_end = multibuffer_start + excerpt.text_summary.lines;
2872            if multibuffer_start.row >= row_range.end {
2873                return None;
2874            }
2875
2876            let mut buffer_start = excerpt.range.context.start;
2877            let mut buffer_end = excerpt.range.context.end;
2878            let excerpt_start_point = buffer_start.to_point(&excerpt.buffer);
2879            let excerpt_end_point = excerpt_start_point + excerpt.text_summary.lines;
2880
2881            if row_range.start > multibuffer_start.row {
2882                let buffer_start_point =
2883                    excerpt_start_point + Point::new(row_range.start - multibuffer_start.row, 0);
2884                buffer_start = excerpt.buffer.anchor_before(buffer_start_point);
2885            }
2886
2887            if row_range.end < multibuffer_end.row {
2888                let buffer_end_point =
2889                    excerpt_start_point + Point::new(row_range.end - multibuffer_start.row, 0);
2890                buffer_end = excerpt.buffer.anchor_before(buffer_end_point);
2891            }
2892
2893            let buffer_hunks = excerpt
2894                .buffer
2895                .git_diff_hunks_intersecting_range_rev(buffer_start..buffer_end)
2896                .filter_map(move |hunk| {
2897                    let start = multibuffer_start.row
2898                        + hunk
2899                            .buffer_range
2900                            .start
2901                            .saturating_sub(excerpt_start_point.row);
2902                    let end = multibuffer_start.row
2903                        + hunk
2904                            .buffer_range
2905                            .end
2906                            .min(excerpt_end_point.row + 1)
2907                            .saturating_sub(excerpt_start_point.row);
2908
2909                    Some(DiffHunk {
2910                        buffer_range: start..end,
2911                        diff_base_byte_range: hunk.diff_base_byte_range.clone(),
2912                    })
2913                });
2914
2915            cursor.prev(&());
2916
2917            Some(buffer_hunks)
2918        })
2919        .flatten()
2920    }
2921
2922    pub fn git_diff_hunks_in_range<'a>(
2923        &'a self,
2924        row_range: Range<u32>,
2925    ) -> impl 'a + Iterator<Item = DiffHunk<u32>> {
2926        let mut cursor = self.excerpts.cursor::<Point>();
2927
2928        cursor.seek(&Point::new(row_range.start, 0), Bias::Right, &());
2929
2930        std::iter::from_fn(move || {
2931            let excerpt = cursor.item()?;
2932            let multibuffer_start = *cursor.start();
2933            let multibuffer_end = multibuffer_start + excerpt.text_summary.lines;
2934            if multibuffer_start.row >= row_range.end {
2935                return None;
2936            }
2937
2938            let mut buffer_start = excerpt.range.context.start;
2939            let mut buffer_end = excerpt.range.context.end;
2940            let excerpt_start_point = buffer_start.to_point(&excerpt.buffer);
2941            let excerpt_end_point = excerpt_start_point + excerpt.text_summary.lines;
2942
2943            if row_range.start > multibuffer_start.row {
2944                let buffer_start_point =
2945                    excerpt_start_point + Point::new(row_range.start - multibuffer_start.row, 0);
2946                buffer_start = excerpt.buffer.anchor_before(buffer_start_point);
2947            }
2948
2949            if row_range.end < multibuffer_end.row {
2950                let buffer_end_point =
2951                    excerpt_start_point + Point::new(row_range.end - multibuffer_start.row, 0);
2952                buffer_end = excerpt.buffer.anchor_before(buffer_end_point);
2953            }
2954
2955            let buffer_hunks = excerpt
2956                .buffer
2957                .git_diff_hunks_intersecting_range(buffer_start..buffer_end)
2958                .filter_map(move |hunk| {
2959                    let start = multibuffer_start.row
2960                        + hunk
2961                            .buffer_range
2962                            .start
2963                            .saturating_sub(excerpt_start_point.row);
2964                    let end = multibuffer_start.row
2965                        + hunk
2966                            .buffer_range
2967                            .end
2968                            .min(excerpt_end_point.row + 1)
2969                            .saturating_sub(excerpt_start_point.row);
2970
2971                    Some(DiffHunk {
2972                        buffer_range: start..end,
2973                        diff_base_byte_range: hunk.diff_base_byte_range.clone(),
2974                    })
2975                });
2976
2977            cursor.next(&());
2978
2979            Some(buffer_hunks)
2980        })
2981        .flatten()
2982    }
2983
2984    pub fn range_for_syntax_ancestor<T: ToOffset>(&self, range: Range<T>) -> Option<Range<usize>> {
2985        let range = range.start.to_offset(self)..range.end.to_offset(self);
2986
2987        self.excerpt_containing(range.clone())
2988            .and_then(|(excerpt, excerpt_offset)| {
2989                let excerpt_buffer_start = excerpt.range.context.start.to_offset(&excerpt.buffer);
2990                let excerpt_buffer_end = excerpt_buffer_start + excerpt.text_summary.len;
2991
2992                let start_in_buffer =
2993                    excerpt_buffer_start + range.start.saturating_sub(excerpt_offset);
2994                let end_in_buffer = excerpt_buffer_start + range.end.saturating_sub(excerpt_offset);
2995                let mut ancestor_buffer_range = excerpt
2996                    .buffer
2997                    .range_for_syntax_ancestor(start_in_buffer..end_in_buffer)?;
2998                ancestor_buffer_range.start =
2999                    cmp::max(ancestor_buffer_range.start, excerpt_buffer_start);
3000                ancestor_buffer_range.end = cmp::min(ancestor_buffer_range.end, excerpt_buffer_end);
3001
3002                let start = excerpt_offset + (ancestor_buffer_range.start - excerpt_buffer_start);
3003                let end = excerpt_offset + (ancestor_buffer_range.end - excerpt_buffer_start);
3004                Some(start..end)
3005            })
3006    }
3007
3008    pub fn outline(&self, theme: Option<&SyntaxTheme>) -> Option<Outline<Anchor>> {
3009        let (excerpt_id, _, buffer) = self.as_singleton()?;
3010        let outline = buffer.outline(theme)?;
3011        Some(Outline::new(
3012            outline
3013                .items
3014                .into_iter()
3015                .map(|item| OutlineItem {
3016                    depth: item.depth,
3017                    range: self.anchor_in_excerpt(excerpt_id.clone(), item.range.start)
3018                        ..self.anchor_in_excerpt(excerpt_id.clone(), item.range.end),
3019                    text: item.text,
3020                    highlight_ranges: item.highlight_ranges,
3021                    name_ranges: item.name_ranges,
3022                })
3023                .collect(),
3024        ))
3025    }
3026
3027    pub fn symbols_containing<T: ToOffset>(
3028        &self,
3029        offset: T,
3030        theme: Option<&SyntaxTheme>,
3031    ) -> Option<(u64, Vec<OutlineItem<Anchor>>)> {
3032        let anchor = self.anchor_before(offset);
3033        let excerpt_id = anchor.excerpt_id();
3034        let excerpt = self.excerpt(excerpt_id)?;
3035        Some((
3036            excerpt.buffer_id,
3037            excerpt
3038                .buffer
3039                .symbols_containing(anchor.text_anchor, theme)
3040                .into_iter()
3041                .flatten()
3042                .map(|item| OutlineItem {
3043                    depth: item.depth,
3044                    range: self.anchor_in_excerpt(excerpt_id, item.range.start)
3045                        ..self.anchor_in_excerpt(excerpt_id, item.range.end),
3046                    text: item.text,
3047                    highlight_ranges: item.highlight_ranges,
3048                    name_ranges: item.name_ranges,
3049                })
3050                .collect(),
3051        ))
3052    }
3053
3054    fn excerpt_locator_for_id<'a>(&'a self, id: ExcerptId) -> &'a Locator {
3055        if id == ExcerptId::min() {
3056            Locator::min_ref()
3057        } else if id == ExcerptId::max() {
3058            Locator::max_ref()
3059        } else {
3060            let mut cursor = self.excerpt_ids.cursor::<ExcerptId>();
3061            cursor.seek(&id, Bias::Left, &());
3062            if let Some(entry) = cursor.item() {
3063                if entry.id == id {
3064                    return &entry.locator;
3065                }
3066            }
3067            panic!("invalid excerpt id {:?}", id)
3068        }
3069    }
3070
3071    pub fn buffer_id_for_excerpt(&self, excerpt_id: ExcerptId) -> Option<u64> {
3072        Some(self.excerpt(excerpt_id)?.buffer_id)
3073    }
3074
3075    pub fn buffer_for_excerpt(&self, excerpt_id: ExcerptId) -> Option<&BufferSnapshot> {
3076        Some(&self.excerpt(excerpt_id)?.buffer)
3077    }
3078
3079    fn excerpt<'a>(&'a self, excerpt_id: ExcerptId) -> Option<&'a Excerpt> {
3080        let mut cursor = self.excerpts.cursor::<Option<&Locator>>();
3081        let locator = self.excerpt_locator_for_id(excerpt_id);
3082        cursor.seek(&Some(locator), Bias::Left, &());
3083        if let Some(excerpt) = cursor.item() {
3084            if excerpt.id == excerpt_id {
3085                return Some(excerpt);
3086            }
3087        }
3088        None
3089    }
3090
3091    /// Returns the excerpt containing range and its offset start within the multibuffer or none if `range` spans multiple excerpts
3092    fn excerpt_containing<'a, T: ToOffset>(
3093        &'a self,
3094        range: Range<T>,
3095    ) -> Option<(&'a Excerpt, usize)> {
3096        let range = range.start.to_offset(self)..range.end.to_offset(self);
3097
3098        let mut cursor = self.excerpts.cursor::<usize>();
3099        cursor.seek(&range.start, Bias::Right, &());
3100        let start_excerpt = cursor.item();
3101
3102        if range.start == range.end {
3103            return start_excerpt.map(|excerpt| (excerpt, *cursor.start()));
3104        }
3105
3106        cursor.seek(&range.end, Bias::Right, &());
3107        let end_excerpt = cursor.item();
3108
3109        start_excerpt
3110            .zip(end_excerpt)
3111            .and_then(|(start_excerpt, end_excerpt)| {
3112                if start_excerpt.id != end_excerpt.id {
3113                    return None;
3114                }
3115
3116                Some((start_excerpt, *cursor.start()))
3117            })
3118    }
3119
3120    pub fn remote_selections_in_range<'a>(
3121        &'a self,
3122        range: &'a Range<Anchor>,
3123    ) -> impl 'a + Iterator<Item = (ReplicaId, bool, CursorShape, Selection<Anchor>)> {
3124        let mut cursor = self.excerpts.cursor::<ExcerptSummary>();
3125        let start_locator = self.excerpt_locator_for_id(range.start.excerpt_id);
3126        let end_locator = self.excerpt_locator_for_id(range.end.excerpt_id);
3127        cursor.seek(start_locator, Bias::Left, &());
3128        cursor
3129            .take_while(move |excerpt| excerpt.locator <= *end_locator)
3130            .flat_map(move |excerpt| {
3131                let mut query_range = excerpt.range.context.start..excerpt.range.context.end;
3132                if excerpt.id == range.start.excerpt_id {
3133                    query_range.start = range.start.text_anchor;
3134                }
3135                if excerpt.id == range.end.excerpt_id {
3136                    query_range.end = range.end.text_anchor;
3137                }
3138
3139                excerpt
3140                    .buffer
3141                    .remote_selections_in_range(query_range)
3142                    .flat_map(move |(replica_id, line_mode, cursor_shape, selections)| {
3143                        selections.map(move |selection| {
3144                            let mut start = Anchor {
3145                                buffer_id: Some(excerpt.buffer_id),
3146                                excerpt_id: excerpt.id.clone(),
3147                                text_anchor: selection.start,
3148                            };
3149                            let mut end = Anchor {
3150                                buffer_id: Some(excerpt.buffer_id),
3151                                excerpt_id: excerpt.id.clone(),
3152                                text_anchor: selection.end,
3153                            };
3154                            if range.start.cmp(&start, self).is_gt() {
3155                                start = range.start.clone();
3156                            }
3157                            if range.end.cmp(&end, self).is_lt() {
3158                                end = range.end.clone();
3159                            }
3160
3161                            (
3162                                replica_id,
3163                                line_mode,
3164                                cursor_shape,
3165                                Selection {
3166                                    id: selection.id,
3167                                    start,
3168                                    end,
3169                                    reversed: selection.reversed,
3170                                    goal: selection.goal,
3171                                },
3172                            )
3173                        })
3174                    })
3175            })
3176    }
3177}
3178
3179#[cfg(any(test, feature = "test-support"))]
3180impl MultiBufferSnapshot {
3181    pub fn random_byte_range(&self, start_offset: usize, rng: &mut impl rand::Rng) -> Range<usize> {
3182        let end = self.clip_offset(rng.gen_range(start_offset..=self.len()), Bias::Right);
3183        let start = self.clip_offset(rng.gen_range(start_offset..=end), Bias::Right);
3184        start..end
3185    }
3186}
3187
3188impl History {
3189    fn start_transaction(&mut self, now: Instant) -> Option<TransactionId> {
3190        self.transaction_depth += 1;
3191        if self.transaction_depth == 1 {
3192            let id = self.next_transaction_id.tick();
3193            self.undo_stack.push(Transaction {
3194                id,
3195                buffer_transactions: Default::default(),
3196                first_edit_at: now,
3197                last_edit_at: now,
3198                suppress_grouping: false,
3199            });
3200            Some(id)
3201        } else {
3202            None
3203        }
3204    }
3205
3206    fn end_transaction(
3207        &mut self,
3208        now: Instant,
3209        buffer_transactions: HashMap<u64, TransactionId>,
3210    ) -> bool {
3211        assert_ne!(self.transaction_depth, 0);
3212        self.transaction_depth -= 1;
3213        if self.transaction_depth == 0 {
3214            if buffer_transactions.is_empty() {
3215                self.undo_stack.pop();
3216                false
3217            } else {
3218                self.redo_stack.clear();
3219                let transaction = self.undo_stack.last_mut().unwrap();
3220                transaction.last_edit_at = now;
3221                for (buffer_id, transaction_id) in buffer_transactions {
3222                    transaction
3223                        .buffer_transactions
3224                        .entry(buffer_id)
3225                        .or_insert(transaction_id);
3226                }
3227                true
3228            }
3229        } else {
3230            false
3231        }
3232    }
3233
3234    fn push_transaction<'a, T>(
3235        &mut self,
3236        buffer_transactions: T,
3237        now: Instant,
3238        cx: &mut ModelContext<MultiBuffer>,
3239    ) where
3240        T: IntoIterator<Item = (&'a ModelHandle<Buffer>, &'a language::Transaction)>,
3241    {
3242        assert_eq!(self.transaction_depth, 0);
3243        let transaction = Transaction {
3244            id: self.next_transaction_id.tick(),
3245            buffer_transactions: buffer_transactions
3246                .into_iter()
3247                .map(|(buffer, transaction)| (buffer.read(cx).remote_id(), transaction.id))
3248                .collect(),
3249            first_edit_at: now,
3250            last_edit_at: now,
3251            suppress_grouping: false,
3252        };
3253        if !transaction.buffer_transactions.is_empty() {
3254            self.undo_stack.push(transaction);
3255            self.redo_stack.clear();
3256        }
3257    }
3258
3259    fn finalize_last_transaction(&mut self) {
3260        if let Some(transaction) = self.undo_stack.last_mut() {
3261            transaction.suppress_grouping = true;
3262        }
3263    }
3264
3265    fn pop_undo(&mut self) -> Option<&mut Transaction> {
3266        assert_eq!(self.transaction_depth, 0);
3267        if let Some(transaction) = self.undo_stack.pop() {
3268            self.redo_stack.push(transaction);
3269            self.redo_stack.last_mut()
3270        } else {
3271            None
3272        }
3273    }
3274
3275    fn pop_redo(&mut self) -> Option<&mut Transaction> {
3276        assert_eq!(self.transaction_depth, 0);
3277        if let Some(transaction) = self.redo_stack.pop() {
3278            self.undo_stack.push(transaction);
3279            self.undo_stack.last_mut()
3280        } else {
3281            None
3282        }
3283    }
3284
3285    fn group(&mut self) -> Option<TransactionId> {
3286        let mut count = 0;
3287        let mut transactions = self.undo_stack.iter();
3288        if let Some(mut transaction) = transactions.next_back() {
3289            while let Some(prev_transaction) = transactions.next_back() {
3290                if !prev_transaction.suppress_grouping
3291                    && transaction.first_edit_at - prev_transaction.last_edit_at
3292                        <= self.group_interval
3293                {
3294                    transaction = prev_transaction;
3295                    count += 1;
3296                } else {
3297                    break;
3298                }
3299            }
3300        }
3301        self.group_trailing(count)
3302    }
3303
3304    fn group_until(&mut self, transaction_id: TransactionId) {
3305        let mut count = 0;
3306        for transaction in self.undo_stack.iter().rev() {
3307            if transaction.id == transaction_id {
3308                self.group_trailing(count);
3309                break;
3310            } else if transaction.suppress_grouping {
3311                break;
3312            } else {
3313                count += 1;
3314            }
3315        }
3316    }
3317
3318    fn group_trailing(&mut self, n: usize) -> Option<TransactionId> {
3319        let new_len = self.undo_stack.len() - n;
3320        let (transactions_to_keep, transactions_to_merge) = self.undo_stack.split_at_mut(new_len);
3321        if let Some(last_transaction) = transactions_to_keep.last_mut() {
3322            if let Some(transaction) = transactions_to_merge.last() {
3323                last_transaction.last_edit_at = transaction.last_edit_at;
3324            }
3325            for to_merge in transactions_to_merge {
3326                for (buffer_id, transaction_id) in &to_merge.buffer_transactions {
3327                    last_transaction
3328                        .buffer_transactions
3329                        .entry(*buffer_id)
3330                        .or_insert(*transaction_id);
3331                }
3332            }
3333        }
3334
3335        self.undo_stack.truncate(new_len);
3336        self.undo_stack.last().map(|t| t.id)
3337    }
3338}
3339
3340impl Excerpt {
3341    fn new(
3342        id: ExcerptId,
3343        locator: Locator,
3344        buffer_id: u64,
3345        buffer: BufferSnapshot,
3346        range: ExcerptRange<text::Anchor>,
3347        has_trailing_newline: bool,
3348    ) -> Self {
3349        Excerpt {
3350            id,
3351            locator,
3352            max_buffer_row: range.context.end.to_point(&buffer).row,
3353            text_summary: buffer
3354                .text_summary_for_range::<TextSummary, _>(range.context.to_offset(&buffer)),
3355            buffer_id,
3356            buffer,
3357            range,
3358            has_trailing_newline,
3359        }
3360    }
3361
3362    fn chunks_in_range(&self, range: Range<usize>, language_aware: bool) -> ExcerptChunks {
3363        let content_start = self.range.context.start.to_offset(&self.buffer);
3364        let chunks_start = content_start + range.start;
3365        let chunks_end = content_start + cmp::min(range.end, self.text_summary.len);
3366
3367        let footer_height = if self.has_trailing_newline
3368            && range.start <= self.text_summary.len
3369            && range.end > self.text_summary.len
3370        {
3371            1
3372        } else {
3373            0
3374        };
3375
3376        let content_chunks = self.buffer.chunks(chunks_start..chunks_end, language_aware);
3377
3378        ExcerptChunks {
3379            content_chunks,
3380            footer_height,
3381        }
3382    }
3383
3384    fn bytes_in_range(&self, range: Range<usize>) -> ExcerptBytes {
3385        let content_start = self.range.context.start.to_offset(&self.buffer);
3386        let bytes_start = content_start + range.start;
3387        let bytes_end = content_start + cmp::min(range.end, self.text_summary.len);
3388        let footer_height = if self.has_trailing_newline
3389            && range.start <= self.text_summary.len
3390            && range.end > self.text_summary.len
3391        {
3392            1
3393        } else {
3394            0
3395        };
3396        let content_bytes = self.buffer.bytes_in_range(bytes_start..bytes_end);
3397
3398        ExcerptBytes {
3399            content_bytes,
3400            footer_height,
3401        }
3402    }
3403
3404    fn clip_anchor(&self, text_anchor: text::Anchor) -> text::Anchor {
3405        if text_anchor
3406            .cmp(&self.range.context.start, &self.buffer)
3407            .is_lt()
3408        {
3409            self.range.context.start
3410        } else if text_anchor
3411            .cmp(&self.range.context.end, &self.buffer)
3412            .is_gt()
3413        {
3414            self.range.context.end
3415        } else {
3416            text_anchor
3417        }
3418    }
3419
3420    fn contains(&self, anchor: &Anchor) -> bool {
3421        Some(self.buffer_id) == anchor.buffer_id
3422            && self
3423                .range
3424                .context
3425                .start
3426                .cmp(&anchor.text_anchor, &self.buffer)
3427                .is_le()
3428            && self
3429                .range
3430                .context
3431                .end
3432                .cmp(&anchor.text_anchor, &self.buffer)
3433                .is_ge()
3434    }
3435}
3436
3437impl ExcerptId {
3438    pub fn min() -> Self {
3439        Self(0)
3440    }
3441
3442    pub fn max() -> Self {
3443        Self(usize::MAX)
3444    }
3445
3446    pub fn to_proto(&self) -> u64 {
3447        self.0 as _
3448    }
3449
3450    pub fn from_proto(proto: u64) -> Self {
3451        Self(proto as _)
3452    }
3453
3454    pub fn cmp(&self, other: &Self, snapshot: &MultiBufferSnapshot) -> cmp::Ordering {
3455        let a = snapshot.excerpt_locator_for_id(*self);
3456        let b = snapshot.excerpt_locator_for_id(*other);
3457        a.cmp(&b).then_with(|| self.0.cmp(&other.0))
3458    }
3459}
3460
3461impl Into<usize> for ExcerptId {
3462    fn into(self) -> usize {
3463        self.0
3464    }
3465}
3466
3467impl fmt::Debug for Excerpt {
3468    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3469        f.debug_struct("Excerpt")
3470            .field("id", &self.id)
3471            .field("locator", &self.locator)
3472            .field("buffer_id", &self.buffer_id)
3473            .field("range", &self.range)
3474            .field("text_summary", &self.text_summary)
3475            .field("has_trailing_newline", &self.has_trailing_newline)
3476            .finish()
3477    }
3478}
3479
3480impl sum_tree::Item for Excerpt {
3481    type Summary = ExcerptSummary;
3482
3483    fn summary(&self) -> Self::Summary {
3484        let mut text = self.text_summary.clone();
3485        if self.has_trailing_newline {
3486            text += TextSummary::from("\n");
3487        }
3488        ExcerptSummary {
3489            excerpt_id: self.id,
3490            excerpt_locator: self.locator.clone(),
3491            max_buffer_row: self.max_buffer_row,
3492            text,
3493        }
3494    }
3495}
3496
3497impl sum_tree::Item for ExcerptIdMapping {
3498    type Summary = ExcerptId;
3499
3500    fn summary(&self) -> Self::Summary {
3501        self.id
3502    }
3503}
3504
3505impl sum_tree::KeyedItem for ExcerptIdMapping {
3506    type Key = ExcerptId;
3507
3508    fn key(&self) -> Self::Key {
3509        self.id
3510    }
3511}
3512
3513impl sum_tree::Summary for ExcerptId {
3514    type Context = ();
3515
3516    fn add_summary(&mut self, other: &Self, _: &()) {
3517        *self = *other;
3518    }
3519}
3520
3521impl sum_tree::Summary for ExcerptSummary {
3522    type Context = ();
3523
3524    fn add_summary(&mut self, summary: &Self, _: &()) {
3525        debug_assert!(summary.excerpt_locator > self.excerpt_locator);
3526        self.excerpt_locator = summary.excerpt_locator.clone();
3527        self.text.add_summary(&summary.text, &());
3528        self.max_buffer_row = cmp::max(self.max_buffer_row, summary.max_buffer_row);
3529    }
3530}
3531
3532impl<'a> sum_tree::Dimension<'a, ExcerptSummary> for TextSummary {
3533    fn add_summary(&mut self, summary: &'a ExcerptSummary, _: &()) {
3534        *self += &summary.text;
3535    }
3536}
3537
3538impl<'a> sum_tree::Dimension<'a, ExcerptSummary> for usize {
3539    fn add_summary(&mut self, summary: &'a ExcerptSummary, _: &()) {
3540        *self += summary.text.len;
3541    }
3542}
3543
3544impl<'a> sum_tree::SeekTarget<'a, ExcerptSummary, ExcerptSummary> for usize {
3545    fn cmp(&self, cursor_location: &ExcerptSummary, _: &()) -> cmp::Ordering {
3546        Ord::cmp(self, &cursor_location.text.len)
3547    }
3548}
3549
3550impl<'a> sum_tree::SeekTarget<'a, ExcerptSummary, Option<&'a Locator>> for Locator {
3551    fn cmp(&self, cursor_location: &Option<&'a Locator>, _: &()) -> cmp::Ordering {
3552        Ord::cmp(&Some(self), cursor_location)
3553    }
3554}
3555
3556impl<'a> sum_tree::SeekTarget<'a, ExcerptSummary, ExcerptSummary> for Locator {
3557    fn cmp(&self, cursor_location: &ExcerptSummary, _: &()) -> cmp::Ordering {
3558        Ord::cmp(self, &cursor_location.excerpt_locator)
3559    }
3560}
3561
3562impl<'a> sum_tree::Dimension<'a, ExcerptSummary> for OffsetUtf16 {
3563    fn add_summary(&mut self, summary: &'a ExcerptSummary, _: &()) {
3564        *self += summary.text.len_utf16;
3565    }
3566}
3567
3568impl<'a> sum_tree::Dimension<'a, ExcerptSummary> for Point {
3569    fn add_summary(&mut self, summary: &'a ExcerptSummary, _: &()) {
3570        *self += summary.text.lines;
3571    }
3572}
3573
3574impl<'a> sum_tree::Dimension<'a, ExcerptSummary> for PointUtf16 {
3575    fn add_summary(&mut self, summary: &'a ExcerptSummary, _: &()) {
3576        *self += summary.text.lines_utf16()
3577    }
3578}
3579
3580impl<'a> sum_tree::Dimension<'a, ExcerptSummary> for Option<&'a Locator> {
3581    fn add_summary(&mut self, summary: &'a ExcerptSummary, _: &()) {
3582        *self = Some(&summary.excerpt_locator);
3583    }
3584}
3585
3586impl<'a> sum_tree::Dimension<'a, ExcerptSummary> for Option<ExcerptId> {
3587    fn add_summary(&mut self, summary: &'a ExcerptSummary, _: &()) {
3588        *self = Some(summary.excerpt_id);
3589    }
3590}
3591
3592impl<'a> MultiBufferRows<'a> {
3593    pub fn seek(&mut self, row: u32) {
3594        self.buffer_row_range = 0..0;
3595
3596        self.excerpts
3597            .seek_forward(&Point::new(row, 0), Bias::Right, &());
3598        if self.excerpts.item().is_none() {
3599            self.excerpts.prev(&());
3600
3601            if self.excerpts.item().is_none() && row == 0 {
3602                self.buffer_row_range = 0..1;
3603                return;
3604            }
3605        }
3606
3607        if let Some(excerpt) = self.excerpts.item() {
3608            let overshoot = row - self.excerpts.start().row;
3609            let excerpt_start = excerpt.range.context.start.to_point(&excerpt.buffer).row;
3610            self.buffer_row_range.start = excerpt_start + overshoot;
3611            self.buffer_row_range.end = excerpt_start + excerpt.text_summary.lines.row + 1;
3612        }
3613    }
3614}
3615
3616impl<'a> Iterator for MultiBufferRows<'a> {
3617    type Item = Option<u32>;
3618
3619    fn next(&mut self) -> Option<Self::Item> {
3620        loop {
3621            if !self.buffer_row_range.is_empty() {
3622                let row = Some(self.buffer_row_range.start);
3623                self.buffer_row_range.start += 1;
3624                return Some(row);
3625            }
3626            self.excerpts.item()?;
3627            self.excerpts.next(&());
3628            let excerpt = self.excerpts.item()?;
3629            self.buffer_row_range.start = excerpt.range.context.start.to_point(&excerpt.buffer).row;
3630            self.buffer_row_range.end =
3631                self.buffer_row_range.start + excerpt.text_summary.lines.row + 1;
3632        }
3633    }
3634}
3635
3636impl<'a> MultiBufferChunks<'a> {
3637    pub fn offset(&self) -> usize {
3638        self.range.start
3639    }
3640
3641    pub fn seek(&mut self, offset: usize) {
3642        self.range.start = offset;
3643        self.excerpts.seek(&offset, Bias::Right, &());
3644        if let Some(excerpt) = self.excerpts.item() {
3645            self.excerpt_chunks = Some(excerpt.chunks_in_range(
3646                self.range.start - self.excerpts.start()..self.range.end - self.excerpts.start(),
3647                self.language_aware,
3648            ));
3649        } else {
3650            self.excerpt_chunks = None;
3651        }
3652    }
3653}
3654
3655impl<'a> Iterator for MultiBufferChunks<'a> {
3656    type Item = Chunk<'a>;
3657
3658    fn next(&mut self) -> Option<Self::Item> {
3659        if self.range.is_empty() {
3660            None
3661        } else if let Some(chunk) = self.excerpt_chunks.as_mut()?.next() {
3662            self.range.start += chunk.text.len();
3663            Some(chunk)
3664        } else {
3665            self.excerpts.next(&());
3666            let excerpt = self.excerpts.item()?;
3667            self.excerpt_chunks = Some(excerpt.chunks_in_range(
3668                0..self.range.end - self.excerpts.start(),
3669                self.language_aware,
3670            ));
3671            self.next()
3672        }
3673    }
3674}
3675
3676impl<'a> MultiBufferBytes<'a> {
3677    fn consume(&mut self, len: usize) {
3678        self.range.start += len;
3679        self.chunk = &self.chunk[len..];
3680
3681        if !self.range.is_empty() && self.chunk.is_empty() {
3682            if let Some(chunk) = self.excerpt_bytes.as_mut().and_then(|bytes| bytes.next()) {
3683                self.chunk = chunk;
3684            } else {
3685                self.excerpts.next(&());
3686                if let Some(excerpt) = self.excerpts.item() {
3687                    let mut excerpt_bytes =
3688                        excerpt.bytes_in_range(0..self.range.end - self.excerpts.start());
3689                    self.chunk = excerpt_bytes.next().unwrap();
3690                    self.excerpt_bytes = Some(excerpt_bytes);
3691                }
3692            }
3693        }
3694    }
3695}
3696
3697impl<'a> Iterator for MultiBufferBytes<'a> {
3698    type Item = &'a [u8];
3699
3700    fn next(&mut self) -> Option<Self::Item> {
3701        let chunk = self.chunk;
3702        if chunk.is_empty() {
3703            None
3704        } else {
3705            self.consume(chunk.len());
3706            Some(chunk)
3707        }
3708    }
3709}
3710
3711impl<'a> io::Read for MultiBufferBytes<'a> {
3712    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
3713        let len = cmp::min(buf.len(), self.chunk.len());
3714        buf[..len].copy_from_slice(&self.chunk[..len]);
3715        if len > 0 {
3716            self.consume(len);
3717        }
3718        Ok(len)
3719    }
3720}
3721
3722impl<'a> Iterator for ExcerptBytes<'a> {
3723    type Item = &'a [u8];
3724
3725    fn next(&mut self) -> Option<Self::Item> {
3726        if let Some(chunk) = self.content_bytes.next() {
3727            if !chunk.is_empty() {
3728                return Some(chunk);
3729            }
3730        }
3731
3732        if self.footer_height > 0 {
3733            let result = &NEWLINES[..self.footer_height];
3734            self.footer_height = 0;
3735            return Some(result);
3736        }
3737
3738        None
3739    }
3740}
3741
3742impl<'a> Iterator for ExcerptChunks<'a> {
3743    type Item = Chunk<'a>;
3744
3745    fn next(&mut self) -> Option<Self::Item> {
3746        if let Some(chunk) = self.content_chunks.next() {
3747            return Some(chunk);
3748        }
3749
3750        if self.footer_height > 0 {
3751            let text = unsafe { str::from_utf8_unchecked(&NEWLINES[..self.footer_height]) };
3752            self.footer_height = 0;
3753            return Some(Chunk {
3754                text,
3755                ..Default::default()
3756            });
3757        }
3758
3759        None
3760    }
3761}
3762
3763impl ToOffset for Point {
3764    fn to_offset<'a>(&self, snapshot: &MultiBufferSnapshot) -> usize {
3765        snapshot.point_to_offset(*self)
3766    }
3767}
3768
3769impl ToOffset for usize {
3770    fn to_offset<'a>(&self, snapshot: &MultiBufferSnapshot) -> usize {
3771        assert!(*self <= snapshot.len(), "offset is out of range");
3772        *self
3773    }
3774}
3775
3776impl ToOffset for OffsetUtf16 {
3777    fn to_offset<'a>(&self, snapshot: &MultiBufferSnapshot) -> usize {
3778        snapshot.offset_utf16_to_offset(*self)
3779    }
3780}
3781
3782impl ToOffset for PointUtf16 {
3783    fn to_offset<'a>(&self, snapshot: &MultiBufferSnapshot) -> usize {
3784        snapshot.point_utf16_to_offset(*self)
3785    }
3786}
3787
3788impl ToOffsetUtf16 for OffsetUtf16 {
3789    fn to_offset_utf16(&self, _snapshot: &MultiBufferSnapshot) -> OffsetUtf16 {
3790        *self
3791    }
3792}
3793
3794impl ToOffsetUtf16 for usize {
3795    fn to_offset_utf16(&self, snapshot: &MultiBufferSnapshot) -> OffsetUtf16 {
3796        snapshot.offset_to_offset_utf16(*self)
3797    }
3798}
3799
3800impl ToPoint for usize {
3801    fn to_point<'a>(&self, snapshot: &MultiBufferSnapshot) -> Point {
3802        snapshot.offset_to_point(*self)
3803    }
3804}
3805
3806impl ToPoint for Point {
3807    fn to_point<'a>(&self, _: &MultiBufferSnapshot) -> Point {
3808        *self
3809    }
3810}
3811
3812impl ToPointUtf16 for usize {
3813    fn to_point_utf16<'a>(&self, snapshot: &MultiBufferSnapshot) -> PointUtf16 {
3814        snapshot.offset_to_point_utf16(*self)
3815    }
3816}
3817
3818impl ToPointUtf16 for Point {
3819    fn to_point_utf16<'a>(&self, snapshot: &MultiBufferSnapshot) -> PointUtf16 {
3820        snapshot.point_to_point_utf16(*self)
3821    }
3822}
3823
3824impl ToPointUtf16 for PointUtf16 {
3825    fn to_point_utf16<'a>(&self, _: &MultiBufferSnapshot) -> PointUtf16 {
3826        *self
3827    }
3828}
3829
3830fn build_excerpt_ranges<T>(
3831    buffer: &BufferSnapshot,
3832    ranges: &[Range<T>],
3833    context_line_count: u32,
3834) -> (Vec<ExcerptRange<Point>>, Vec<usize>)
3835where
3836    T: text::ToPoint,
3837{
3838    let max_point = buffer.max_point();
3839    let mut range_counts = Vec::new();
3840    let mut excerpt_ranges = Vec::new();
3841    let mut range_iter = ranges
3842        .iter()
3843        .map(|range| range.start.to_point(buffer)..range.end.to_point(buffer))
3844        .peekable();
3845    while let Some(range) = range_iter.next() {
3846        let excerpt_start = Point::new(range.start.row.saturating_sub(context_line_count), 0);
3847        let mut excerpt_end = Point::new(range.end.row + 1 + context_line_count, 0).min(max_point);
3848        let mut ranges_in_excerpt = 1;
3849
3850        while let Some(next_range) = range_iter.peek() {
3851            if next_range.start.row <= excerpt_end.row + context_line_count {
3852                excerpt_end =
3853                    Point::new(next_range.end.row + 1 + context_line_count, 0).min(max_point);
3854                ranges_in_excerpt += 1;
3855                range_iter.next();
3856            } else {
3857                break;
3858            }
3859        }
3860
3861        excerpt_ranges.push(ExcerptRange {
3862            context: excerpt_start..excerpt_end,
3863            primary: Some(range),
3864        });
3865        range_counts.push(ranges_in_excerpt);
3866    }
3867
3868    (excerpt_ranges, range_counts)
3869}
3870
3871#[cfg(test)]
3872mod tests {
3873    use super::*;
3874    use futures::StreamExt;
3875    use gpui::{AppContext, TestAppContext};
3876    use language::{Buffer, Rope};
3877    use rand::prelude::*;
3878    use settings::SettingsStore;
3879    use std::{env, rc::Rc};
3880    use unindent::Unindent;
3881    use util::test::sample_text;
3882
3883    #[gpui::test]
3884    fn test_singleton(cx: &mut AppContext) {
3885        let buffer = cx.add_model(|cx| Buffer::new(0, sample_text(6, 6, 'a'), cx));
3886        let multibuffer = cx.add_model(|cx| MultiBuffer::singleton(buffer.clone(), cx));
3887
3888        let snapshot = multibuffer.read(cx).snapshot(cx);
3889        assert_eq!(snapshot.text(), buffer.read(cx).text());
3890
3891        assert_eq!(
3892            snapshot.buffer_rows(0).collect::<Vec<_>>(),
3893            (0..buffer.read(cx).row_count())
3894                .map(Some)
3895                .collect::<Vec<_>>()
3896        );
3897
3898        buffer.update(cx, |buffer, cx| buffer.edit([(1..3, "XXX\n")], None, cx));
3899        let snapshot = multibuffer.read(cx).snapshot(cx);
3900
3901        assert_eq!(snapshot.text(), buffer.read(cx).text());
3902        assert_eq!(
3903            snapshot.buffer_rows(0).collect::<Vec<_>>(),
3904            (0..buffer.read(cx).row_count())
3905                .map(Some)
3906                .collect::<Vec<_>>()
3907        );
3908    }
3909
3910    #[gpui::test]
3911    fn test_remote(cx: &mut AppContext) {
3912        let host_buffer = cx.add_model(|cx| Buffer::new(0, "a", cx));
3913        let guest_buffer = cx.add_model(|cx| {
3914            let state = host_buffer.read(cx).to_proto();
3915            let ops = cx
3916                .background()
3917                .block(host_buffer.read(cx).serialize_ops(None, cx));
3918            let mut buffer = Buffer::from_proto(1, state, None).unwrap();
3919            buffer
3920                .apply_ops(
3921                    ops.into_iter()
3922                        .map(|op| language::proto::deserialize_operation(op).unwrap()),
3923                    cx,
3924                )
3925                .unwrap();
3926            buffer
3927        });
3928        let multibuffer = cx.add_model(|cx| MultiBuffer::singleton(guest_buffer.clone(), cx));
3929        let snapshot = multibuffer.read(cx).snapshot(cx);
3930        assert_eq!(snapshot.text(), "a");
3931
3932        guest_buffer.update(cx, |buffer, cx| buffer.edit([(1..1, "b")], None, cx));
3933        let snapshot = multibuffer.read(cx).snapshot(cx);
3934        assert_eq!(snapshot.text(), "ab");
3935
3936        guest_buffer.update(cx, |buffer, cx| buffer.edit([(2..2, "c")], None, cx));
3937        let snapshot = multibuffer.read(cx).snapshot(cx);
3938        assert_eq!(snapshot.text(), "abc");
3939    }
3940
3941    #[gpui::test]
3942    fn test_excerpt_boundaries_and_clipping(cx: &mut AppContext) {
3943        let buffer_1 = cx.add_model(|cx| Buffer::new(0, sample_text(6, 6, 'a'), cx));
3944        let buffer_2 = cx.add_model(|cx| Buffer::new(0, sample_text(6, 6, 'g'), cx));
3945        let multibuffer = cx.add_model(|_| MultiBuffer::new(0));
3946
3947        let events = Rc::new(RefCell::new(Vec::<Event>::new()));
3948        multibuffer.update(cx, |_, cx| {
3949            let events = events.clone();
3950            cx.subscribe(&multibuffer, move |_, _, event, _| {
3951                if let Event::Edited = event {
3952                    events.borrow_mut().push(event.clone())
3953                }
3954            })
3955            .detach();
3956        });
3957
3958        let subscription = multibuffer.update(cx, |multibuffer, cx| {
3959            let subscription = multibuffer.subscribe();
3960            multibuffer.push_excerpts(
3961                buffer_1.clone(),
3962                [ExcerptRange {
3963                    context: Point::new(1, 2)..Point::new(2, 5),
3964                    primary: None,
3965                }],
3966                cx,
3967            );
3968            assert_eq!(
3969                subscription.consume().into_inner(),
3970                [Edit {
3971                    old: 0..0,
3972                    new: 0..10
3973                }]
3974            );
3975
3976            multibuffer.push_excerpts(
3977                buffer_1.clone(),
3978                [ExcerptRange {
3979                    context: Point::new(3, 3)..Point::new(4, 4),
3980                    primary: None,
3981                }],
3982                cx,
3983            );
3984            multibuffer.push_excerpts(
3985                buffer_2.clone(),
3986                [ExcerptRange {
3987                    context: Point::new(3, 1)..Point::new(3, 3),
3988                    primary: None,
3989                }],
3990                cx,
3991            );
3992            assert_eq!(
3993                subscription.consume().into_inner(),
3994                [Edit {
3995                    old: 10..10,
3996                    new: 10..22
3997                }]
3998            );
3999
4000            subscription
4001        });
4002
4003        // Adding excerpts emits an edited event.
4004        assert_eq!(
4005            events.borrow().as_slice(),
4006            &[Event::Edited, Event::Edited, Event::Edited]
4007        );
4008
4009        let snapshot = multibuffer.read(cx).snapshot(cx);
4010        assert_eq!(
4011            snapshot.text(),
4012            concat!(
4013                "bbbb\n",  // Preserve newlines
4014                "ccccc\n", //
4015                "ddd\n",   //
4016                "eeee\n",  //
4017                "jj"       //
4018            )
4019        );
4020        assert_eq!(
4021            snapshot.buffer_rows(0).collect::<Vec<_>>(),
4022            [Some(1), Some(2), Some(3), Some(4), Some(3)]
4023        );
4024        assert_eq!(
4025            snapshot.buffer_rows(2).collect::<Vec<_>>(),
4026            [Some(3), Some(4), Some(3)]
4027        );
4028        assert_eq!(snapshot.buffer_rows(4).collect::<Vec<_>>(), [Some(3)]);
4029        assert_eq!(snapshot.buffer_rows(5).collect::<Vec<_>>(), []);
4030
4031        assert_eq!(
4032            boundaries_in_range(Point::new(0, 0)..Point::new(4, 2), &snapshot),
4033            &[
4034                (0, "bbbb\nccccc".to_string(), true),
4035                (2, "ddd\neeee".to_string(), false),
4036                (4, "jj".to_string(), true),
4037            ]
4038        );
4039        assert_eq!(
4040            boundaries_in_range(Point::new(0, 0)..Point::new(2, 0), &snapshot),
4041            &[(0, "bbbb\nccccc".to_string(), true)]
4042        );
4043        assert_eq!(
4044            boundaries_in_range(Point::new(1, 0)..Point::new(1, 5), &snapshot),
4045            &[]
4046        );
4047        assert_eq!(
4048            boundaries_in_range(Point::new(1, 0)..Point::new(2, 0), &snapshot),
4049            &[]
4050        );
4051        assert_eq!(
4052            boundaries_in_range(Point::new(1, 0)..Point::new(4, 0), &snapshot),
4053            &[(2, "ddd\neeee".to_string(), false)]
4054        );
4055        assert_eq!(
4056            boundaries_in_range(Point::new(1, 0)..Point::new(4, 0), &snapshot),
4057            &[(2, "ddd\neeee".to_string(), false)]
4058        );
4059        assert_eq!(
4060            boundaries_in_range(Point::new(2, 0)..Point::new(3, 0), &snapshot),
4061            &[(2, "ddd\neeee".to_string(), false)]
4062        );
4063        assert_eq!(
4064            boundaries_in_range(Point::new(4, 0)..Point::new(4, 2), &snapshot),
4065            &[(4, "jj".to_string(), true)]
4066        );
4067        assert_eq!(
4068            boundaries_in_range(Point::new(4, 2)..Point::new(4, 2), &snapshot),
4069            &[]
4070        );
4071
4072        buffer_1.update(cx, |buffer, cx| {
4073            let text = "\n";
4074            buffer.edit(
4075                [
4076                    (Point::new(0, 0)..Point::new(0, 0), text),
4077                    (Point::new(2, 1)..Point::new(2, 3), text),
4078                ],
4079                None,
4080                cx,
4081            );
4082        });
4083
4084        let snapshot = multibuffer.read(cx).snapshot(cx);
4085        assert_eq!(
4086            snapshot.text(),
4087            concat!(
4088                "bbbb\n", // Preserve newlines
4089                "c\n",    //
4090                "cc\n",   //
4091                "ddd\n",  //
4092                "eeee\n", //
4093                "jj"      //
4094            )
4095        );
4096
4097        assert_eq!(
4098            subscription.consume().into_inner(),
4099            [Edit {
4100                old: 6..8,
4101                new: 6..7
4102            }]
4103        );
4104
4105        let snapshot = multibuffer.read(cx).snapshot(cx);
4106        assert_eq!(
4107            snapshot.clip_point(Point::new(0, 5), Bias::Left),
4108            Point::new(0, 4)
4109        );
4110        assert_eq!(
4111            snapshot.clip_point(Point::new(0, 5), Bias::Right),
4112            Point::new(0, 4)
4113        );
4114        assert_eq!(
4115            snapshot.clip_point(Point::new(5, 1), Bias::Right),
4116            Point::new(5, 1)
4117        );
4118        assert_eq!(
4119            snapshot.clip_point(Point::new(5, 2), Bias::Right),
4120            Point::new(5, 2)
4121        );
4122        assert_eq!(
4123            snapshot.clip_point(Point::new(5, 3), Bias::Right),
4124            Point::new(5, 2)
4125        );
4126
4127        let snapshot = multibuffer.update(cx, |multibuffer, cx| {
4128            let (buffer_2_excerpt_id, _) =
4129                multibuffer.excerpts_for_buffer(&buffer_2, cx)[0].clone();
4130            multibuffer.remove_excerpts([buffer_2_excerpt_id], cx);
4131            multibuffer.snapshot(cx)
4132        });
4133
4134        assert_eq!(
4135            snapshot.text(),
4136            concat!(
4137                "bbbb\n", // Preserve newlines
4138                "c\n",    //
4139                "cc\n",   //
4140                "ddd\n",  //
4141                "eeee",   //
4142            )
4143        );
4144
4145        fn boundaries_in_range(
4146            range: Range<Point>,
4147            snapshot: &MultiBufferSnapshot,
4148        ) -> Vec<(u32, String, bool)> {
4149            snapshot
4150                .excerpt_boundaries_in_range(range)
4151                .map(|boundary| {
4152                    (
4153                        boundary.row,
4154                        boundary
4155                            .buffer
4156                            .text_for_range(boundary.range.context)
4157                            .collect::<String>(),
4158                        boundary.starts_new_buffer,
4159                    )
4160                })
4161                .collect::<Vec<_>>()
4162        }
4163    }
4164
4165    #[gpui::test]
4166    fn test_excerpt_events(cx: &mut AppContext) {
4167        let buffer_1 = cx.add_model(|cx| Buffer::new(0, sample_text(10, 3, 'a'), cx));
4168        let buffer_2 = cx.add_model(|cx| Buffer::new(0, sample_text(10, 3, 'm'), cx));
4169
4170        let leader_multibuffer = cx.add_model(|_| MultiBuffer::new(0));
4171        let follower_multibuffer = cx.add_model(|_| MultiBuffer::new(0));
4172        let follower_edit_event_count = Rc::new(RefCell::new(0));
4173
4174        follower_multibuffer.update(cx, |_, cx| {
4175            let follower_edit_event_count = follower_edit_event_count.clone();
4176            cx.subscribe(
4177                &leader_multibuffer,
4178                move |follower, _, event, cx| match event.clone() {
4179                    Event::ExcerptsAdded {
4180                        buffer,
4181                        predecessor,
4182                        excerpts,
4183                    } => follower.insert_excerpts_with_ids_after(predecessor, buffer, excerpts, cx),
4184                    Event::ExcerptsRemoved { ids } => follower.remove_excerpts(ids, cx),
4185                    Event::Edited => {
4186                        *follower_edit_event_count.borrow_mut() += 1;
4187                    }
4188                    _ => {}
4189                },
4190            )
4191            .detach();
4192        });
4193
4194        leader_multibuffer.update(cx, |leader, cx| {
4195            leader.push_excerpts(
4196                buffer_1.clone(),
4197                [
4198                    ExcerptRange {
4199                        context: 0..8,
4200                        primary: None,
4201                    },
4202                    ExcerptRange {
4203                        context: 12..16,
4204                        primary: None,
4205                    },
4206                ],
4207                cx,
4208            );
4209            leader.insert_excerpts_after(
4210                leader.excerpt_ids()[0],
4211                buffer_2.clone(),
4212                [
4213                    ExcerptRange {
4214                        context: 0..5,
4215                        primary: None,
4216                    },
4217                    ExcerptRange {
4218                        context: 10..15,
4219                        primary: None,
4220                    },
4221                ],
4222                cx,
4223            )
4224        });
4225        assert_eq!(
4226            leader_multibuffer.read(cx).snapshot(cx).text(),
4227            follower_multibuffer.read(cx).snapshot(cx).text(),
4228        );
4229        assert_eq!(*follower_edit_event_count.borrow(), 2);
4230
4231        leader_multibuffer.update(cx, |leader, cx| {
4232            let excerpt_ids = leader.excerpt_ids();
4233            leader.remove_excerpts([excerpt_ids[1], excerpt_ids[3]], cx);
4234        });
4235        assert_eq!(
4236            leader_multibuffer.read(cx).snapshot(cx).text(),
4237            follower_multibuffer.read(cx).snapshot(cx).text(),
4238        );
4239        assert_eq!(*follower_edit_event_count.borrow(), 3);
4240
4241        // Removing an empty set of excerpts is a noop.
4242        leader_multibuffer.update(cx, |leader, cx| {
4243            leader.remove_excerpts([], cx);
4244        });
4245        assert_eq!(
4246            leader_multibuffer.read(cx).snapshot(cx).text(),
4247            follower_multibuffer.read(cx).snapshot(cx).text(),
4248        );
4249        assert_eq!(*follower_edit_event_count.borrow(), 3);
4250
4251        // Adding an empty set of excerpts is a noop.
4252        leader_multibuffer.update(cx, |leader, cx| {
4253            leader.push_excerpts::<usize>(buffer_2.clone(), [], cx);
4254        });
4255        assert_eq!(
4256            leader_multibuffer.read(cx).snapshot(cx).text(),
4257            follower_multibuffer.read(cx).snapshot(cx).text(),
4258        );
4259        assert_eq!(*follower_edit_event_count.borrow(), 3);
4260
4261        leader_multibuffer.update(cx, |leader, cx| {
4262            leader.clear(cx);
4263        });
4264        assert_eq!(
4265            leader_multibuffer.read(cx).snapshot(cx).text(),
4266            follower_multibuffer.read(cx).snapshot(cx).text(),
4267        );
4268        assert_eq!(*follower_edit_event_count.borrow(), 4);
4269    }
4270
4271    #[gpui::test]
4272    fn test_push_excerpts_with_context_lines(cx: &mut AppContext) {
4273        let buffer = cx.add_model(|cx| Buffer::new(0, sample_text(20, 3, 'a'), cx));
4274        let multibuffer = cx.add_model(|_| MultiBuffer::new(0));
4275        let anchor_ranges = multibuffer.update(cx, |multibuffer, cx| {
4276            multibuffer.push_excerpts_with_context_lines(
4277                buffer.clone(),
4278                vec![
4279                    Point::new(3, 2)..Point::new(4, 2),
4280                    Point::new(7, 1)..Point::new(7, 3),
4281                    Point::new(15, 0)..Point::new(15, 0),
4282                ],
4283                2,
4284                cx,
4285            )
4286        });
4287
4288        let snapshot = multibuffer.read(cx).snapshot(cx);
4289        assert_eq!(
4290            snapshot.text(),
4291            "bbb\nccc\nddd\neee\nfff\nggg\nhhh\niii\njjj\n\nnnn\nooo\nppp\nqqq\nrrr\n"
4292        );
4293
4294        assert_eq!(
4295            anchor_ranges
4296                .iter()
4297                .map(|range| range.to_point(&snapshot))
4298                .collect::<Vec<_>>(),
4299            vec![
4300                Point::new(2, 2)..Point::new(3, 2),
4301                Point::new(6, 1)..Point::new(6, 3),
4302                Point::new(12, 0)..Point::new(12, 0)
4303            ]
4304        );
4305    }
4306
4307    #[gpui::test]
4308    async fn test_stream_excerpts_with_context_lines(cx: &mut TestAppContext) {
4309        let buffer = cx.add_model(|cx| Buffer::new(0, sample_text(20, 3, 'a'), cx));
4310        let multibuffer = cx.add_model(|_| MultiBuffer::new(0));
4311        let (task, anchor_ranges) = multibuffer.update(cx, |multibuffer, cx| {
4312            let snapshot = buffer.read(cx);
4313            let ranges = vec![
4314                snapshot.anchor_before(Point::new(3, 2))..snapshot.anchor_before(Point::new(4, 2)),
4315                snapshot.anchor_before(Point::new(7, 1))..snapshot.anchor_before(Point::new(7, 3)),
4316                snapshot.anchor_before(Point::new(15, 0))
4317                    ..snapshot.anchor_before(Point::new(15, 0)),
4318            ];
4319            multibuffer.stream_excerpts_with_context_lines(vec![(buffer.clone(), ranges)], 2, cx)
4320        });
4321
4322        let anchor_ranges = anchor_ranges.collect::<Vec<_>>().await;
4323        // Ensure task is finished when stream completes.
4324        task.await;
4325
4326        let snapshot = multibuffer.read_with(cx, |multibuffer, cx| multibuffer.snapshot(cx));
4327        assert_eq!(
4328            snapshot.text(),
4329            "bbb\nccc\nddd\neee\nfff\nggg\nhhh\niii\njjj\n\nnnn\nooo\nppp\nqqq\nrrr\n"
4330        );
4331
4332        assert_eq!(
4333            anchor_ranges
4334                .iter()
4335                .map(|range| range.to_point(&snapshot))
4336                .collect::<Vec<_>>(),
4337            vec![
4338                Point::new(2, 2)..Point::new(3, 2),
4339                Point::new(6, 1)..Point::new(6, 3),
4340                Point::new(12, 0)..Point::new(12, 0)
4341            ]
4342        );
4343    }
4344
4345    #[gpui::test]
4346    fn test_empty_multibuffer(cx: &mut AppContext) {
4347        let multibuffer = cx.add_model(|_| MultiBuffer::new(0));
4348
4349        let snapshot = multibuffer.read(cx).snapshot(cx);
4350        assert_eq!(snapshot.text(), "");
4351        assert_eq!(snapshot.buffer_rows(0).collect::<Vec<_>>(), &[Some(0)]);
4352        assert_eq!(snapshot.buffer_rows(1).collect::<Vec<_>>(), &[]);
4353    }
4354
4355    #[gpui::test]
4356    fn test_singleton_multibuffer_anchors(cx: &mut AppContext) {
4357        let buffer = cx.add_model(|cx| Buffer::new(0, "abcd", cx));
4358        let multibuffer = cx.add_model(|cx| MultiBuffer::singleton(buffer.clone(), cx));
4359        let old_snapshot = multibuffer.read(cx).snapshot(cx);
4360        buffer.update(cx, |buffer, cx| {
4361            buffer.edit([(0..0, "X")], None, cx);
4362            buffer.edit([(5..5, "Y")], None, cx);
4363        });
4364        let new_snapshot = multibuffer.read(cx).snapshot(cx);
4365
4366        assert_eq!(old_snapshot.text(), "abcd");
4367        assert_eq!(new_snapshot.text(), "XabcdY");
4368
4369        assert_eq!(old_snapshot.anchor_before(0).to_offset(&new_snapshot), 0);
4370        assert_eq!(old_snapshot.anchor_after(0).to_offset(&new_snapshot), 1);
4371        assert_eq!(old_snapshot.anchor_before(4).to_offset(&new_snapshot), 5);
4372        assert_eq!(old_snapshot.anchor_after(4).to_offset(&new_snapshot), 6);
4373    }
4374
4375    #[gpui::test]
4376    fn test_multibuffer_anchors(cx: &mut AppContext) {
4377        let buffer_1 = cx.add_model(|cx| Buffer::new(0, "abcd", cx));
4378        let buffer_2 = cx.add_model(|cx| Buffer::new(0, "efghi", cx));
4379        let multibuffer = cx.add_model(|cx| {
4380            let mut multibuffer = MultiBuffer::new(0);
4381            multibuffer.push_excerpts(
4382                buffer_1.clone(),
4383                [ExcerptRange {
4384                    context: 0..4,
4385                    primary: None,
4386                }],
4387                cx,
4388            );
4389            multibuffer.push_excerpts(
4390                buffer_2.clone(),
4391                [ExcerptRange {
4392                    context: 0..5,
4393                    primary: None,
4394                }],
4395                cx,
4396            );
4397            multibuffer
4398        });
4399        let old_snapshot = multibuffer.read(cx).snapshot(cx);
4400
4401        assert_eq!(old_snapshot.anchor_before(0).to_offset(&old_snapshot), 0);
4402        assert_eq!(old_snapshot.anchor_after(0).to_offset(&old_snapshot), 0);
4403        assert_eq!(Anchor::min().to_offset(&old_snapshot), 0);
4404        assert_eq!(Anchor::min().to_offset(&old_snapshot), 0);
4405        assert_eq!(Anchor::max().to_offset(&old_snapshot), 10);
4406        assert_eq!(Anchor::max().to_offset(&old_snapshot), 10);
4407
4408        buffer_1.update(cx, |buffer, cx| {
4409            buffer.edit([(0..0, "W")], None, cx);
4410            buffer.edit([(5..5, "X")], None, cx);
4411        });
4412        buffer_2.update(cx, |buffer, cx| {
4413            buffer.edit([(0..0, "Y")], None, cx);
4414            buffer.edit([(6..6, "Z")], None, cx);
4415        });
4416        let new_snapshot = multibuffer.read(cx).snapshot(cx);
4417
4418        assert_eq!(old_snapshot.text(), "abcd\nefghi");
4419        assert_eq!(new_snapshot.text(), "WabcdX\nYefghiZ");
4420
4421        assert_eq!(old_snapshot.anchor_before(0).to_offset(&new_snapshot), 0);
4422        assert_eq!(old_snapshot.anchor_after(0).to_offset(&new_snapshot), 1);
4423        assert_eq!(old_snapshot.anchor_before(1).to_offset(&new_snapshot), 2);
4424        assert_eq!(old_snapshot.anchor_after(1).to_offset(&new_snapshot), 2);
4425        assert_eq!(old_snapshot.anchor_before(2).to_offset(&new_snapshot), 3);
4426        assert_eq!(old_snapshot.anchor_after(2).to_offset(&new_snapshot), 3);
4427        assert_eq!(old_snapshot.anchor_before(5).to_offset(&new_snapshot), 7);
4428        assert_eq!(old_snapshot.anchor_after(5).to_offset(&new_snapshot), 8);
4429        assert_eq!(old_snapshot.anchor_before(10).to_offset(&new_snapshot), 13);
4430        assert_eq!(old_snapshot.anchor_after(10).to_offset(&new_snapshot), 14);
4431    }
4432
4433    #[gpui::test]
4434    fn test_resolving_anchors_after_replacing_their_excerpts(cx: &mut AppContext) {
4435        let buffer_1 = cx.add_model(|cx| Buffer::new(0, "abcd", cx));
4436        let buffer_2 = cx.add_model(|cx| Buffer::new(0, "ABCDEFGHIJKLMNOP", cx));
4437        let multibuffer = cx.add_model(|_| MultiBuffer::new(0));
4438
4439        // Create an insertion id in buffer 1 that doesn't exist in buffer 2.
4440        // Add an excerpt from buffer 1 that spans this new insertion.
4441        buffer_1.update(cx, |buffer, cx| buffer.edit([(4..4, "123")], None, cx));
4442        let excerpt_id_1 = multibuffer.update(cx, |multibuffer, cx| {
4443            multibuffer
4444                .push_excerpts(
4445                    buffer_1.clone(),
4446                    [ExcerptRange {
4447                        context: 0..7,
4448                        primary: None,
4449                    }],
4450                    cx,
4451                )
4452                .pop()
4453                .unwrap()
4454        });
4455
4456        let snapshot_1 = multibuffer.read(cx).snapshot(cx);
4457        assert_eq!(snapshot_1.text(), "abcd123");
4458
4459        // Replace the buffer 1 excerpt with new excerpts from buffer 2.
4460        let (excerpt_id_2, excerpt_id_3) = multibuffer.update(cx, |multibuffer, cx| {
4461            multibuffer.remove_excerpts([excerpt_id_1], cx);
4462            let mut ids = multibuffer
4463                .push_excerpts(
4464                    buffer_2.clone(),
4465                    [
4466                        ExcerptRange {
4467                            context: 0..4,
4468                            primary: None,
4469                        },
4470                        ExcerptRange {
4471                            context: 6..10,
4472                            primary: None,
4473                        },
4474                        ExcerptRange {
4475                            context: 12..16,
4476                            primary: None,
4477                        },
4478                    ],
4479                    cx,
4480                )
4481                .into_iter();
4482            (ids.next().unwrap(), ids.next().unwrap())
4483        });
4484        let snapshot_2 = multibuffer.read(cx).snapshot(cx);
4485        assert_eq!(snapshot_2.text(), "ABCD\nGHIJ\nMNOP");
4486
4487        // The old excerpt id doesn't get reused.
4488        assert_ne!(excerpt_id_2, excerpt_id_1);
4489
4490        // Resolve some anchors from the previous snapshot in the new snapshot.
4491        // The current excerpts are from a different buffer, so we don't attempt to
4492        // resolve the old text anchor in the new buffer.
4493        assert_eq!(
4494            snapshot_2.summary_for_anchor::<usize>(&snapshot_1.anchor_before(2)),
4495            0
4496        );
4497        assert_eq!(
4498            snapshot_2.summaries_for_anchors::<usize, _>(&[
4499                snapshot_1.anchor_before(2),
4500                snapshot_1.anchor_after(3)
4501            ]),
4502            vec![0, 0]
4503        );
4504
4505        // Refresh anchors from the old snapshot. The return value indicates that both
4506        // anchors lost their original excerpt.
4507        let refresh =
4508            snapshot_2.refresh_anchors(&[snapshot_1.anchor_before(2), snapshot_1.anchor_after(3)]);
4509        assert_eq!(
4510            refresh,
4511            &[
4512                (0, snapshot_2.anchor_before(0), false),
4513                (1, snapshot_2.anchor_after(0), false),
4514            ]
4515        );
4516
4517        // Replace the middle excerpt with a smaller excerpt in buffer 2,
4518        // that intersects the old excerpt.
4519        let excerpt_id_5 = multibuffer.update(cx, |multibuffer, cx| {
4520            multibuffer.remove_excerpts([excerpt_id_3], cx);
4521            multibuffer
4522                .insert_excerpts_after(
4523                    excerpt_id_2,
4524                    buffer_2.clone(),
4525                    [ExcerptRange {
4526                        context: 5..8,
4527                        primary: None,
4528                    }],
4529                    cx,
4530                )
4531                .pop()
4532                .unwrap()
4533        });
4534
4535        let snapshot_3 = multibuffer.read(cx).snapshot(cx);
4536        assert_eq!(snapshot_3.text(), "ABCD\nFGH\nMNOP");
4537        assert_ne!(excerpt_id_5, excerpt_id_3);
4538
4539        // Resolve some anchors from the previous snapshot in the new snapshot.
4540        // The third anchor can't be resolved, since its excerpt has been removed,
4541        // so it resolves to the same position as its predecessor.
4542        let anchors = [
4543            snapshot_2.anchor_before(0),
4544            snapshot_2.anchor_after(2),
4545            snapshot_2.anchor_after(6),
4546            snapshot_2.anchor_after(14),
4547        ];
4548        assert_eq!(
4549            snapshot_3.summaries_for_anchors::<usize, _>(&anchors),
4550            &[0, 2, 9, 13]
4551        );
4552
4553        let new_anchors = snapshot_3.refresh_anchors(&anchors);
4554        assert_eq!(
4555            new_anchors.iter().map(|a| (a.0, a.2)).collect::<Vec<_>>(),
4556            &[(0, true), (1, true), (2, true), (3, true)]
4557        );
4558        assert_eq!(
4559            snapshot_3.summaries_for_anchors::<usize, _>(new_anchors.iter().map(|a| &a.1)),
4560            &[0, 2, 7, 13]
4561        );
4562    }
4563
4564    #[gpui::test]
4565    async fn test_diff_hunks_in_range(cx: &mut TestAppContext) {
4566        use git::diff::DiffHunkStatus;
4567
4568        // buffer has two modified hunks with two rows each
4569        let buffer_1 = cx.add_model(|cx| {
4570            let mut buffer = Buffer::new(
4571                0,
4572                "
4573                1.zero
4574                1.ONE
4575                1.TWO
4576                1.three
4577                1.FOUR
4578                1.FIVE
4579                1.six
4580            "
4581                .unindent(),
4582                cx,
4583            );
4584            buffer.set_diff_base(
4585                Some(
4586                    "
4587                1.zero
4588                1.one
4589                1.two
4590                1.three
4591                1.four
4592                1.five
4593                1.six
4594            "
4595                    .unindent(),
4596                ),
4597                cx,
4598            );
4599            buffer
4600        });
4601
4602        // buffer has a deletion hunk and an insertion hunk
4603        let buffer_2 = cx.add_model(|cx| {
4604            let mut buffer = Buffer::new(
4605                0,
4606                "
4607                2.zero
4608                2.one
4609                2.two
4610                2.three
4611                2.four
4612                2.five
4613                2.six
4614            "
4615                .unindent(),
4616                cx,
4617            );
4618            buffer.set_diff_base(
4619                Some(
4620                    "
4621                2.zero
4622                2.one
4623                2.one-and-a-half
4624                2.two
4625                2.three
4626                2.four
4627                2.six
4628            "
4629                    .unindent(),
4630                ),
4631                cx,
4632            );
4633            buffer
4634        });
4635
4636        cx.foreground().run_until_parked();
4637
4638        let multibuffer = cx.add_model(|cx| {
4639            let mut multibuffer = MultiBuffer::new(0);
4640            multibuffer.push_excerpts(
4641                buffer_1.clone(),
4642                [
4643                    // excerpt ends in the middle of a modified hunk
4644                    ExcerptRange {
4645                        context: Point::new(0, 0)..Point::new(1, 5),
4646                        primary: Default::default(),
4647                    },
4648                    // excerpt begins in the middle of a modified hunk
4649                    ExcerptRange {
4650                        context: Point::new(5, 0)..Point::new(6, 5),
4651                        primary: Default::default(),
4652                    },
4653                ],
4654                cx,
4655            );
4656            multibuffer.push_excerpts(
4657                buffer_2.clone(),
4658                [
4659                    // excerpt ends at a deletion
4660                    ExcerptRange {
4661                        context: Point::new(0, 0)..Point::new(1, 5),
4662                        primary: Default::default(),
4663                    },
4664                    // excerpt starts at a deletion
4665                    ExcerptRange {
4666                        context: Point::new(2, 0)..Point::new(2, 5),
4667                        primary: Default::default(),
4668                    },
4669                    // excerpt fully contains a deletion hunk
4670                    ExcerptRange {
4671                        context: Point::new(1, 0)..Point::new(2, 5),
4672                        primary: Default::default(),
4673                    },
4674                    // excerpt fully contains an insertion hunk
4675                    ExcerptRange {
4676                        context: Point::new(4, 0)..Point::new(6, 5),
4677                        primary: Default::default(),
4678                    },
4679                ],
4680                cx,
4681            );
4682            multibuffer
4683        });
4684
4685        let snapshot = multibuffer.read_with(cx, |b, cx| b.snapshot(cx));
4686
4687        assert_eq!(
4688            snapshot.text(),
4689            "
4690                1.zero
4691                1.ONE
4692                1.FIVE
4693                1.six
4694                2.zero
4695                2.one
4696                2.two
4697                2.one
4698                2.two
4699                2.four
4700                2.five
4701                2.six"
4702                .unindent()
4703        );
4704
4705        let expected = [
4706            (DiffHunkStatus::Modified, 1..2),
4707            (DiffHunkStatus::Modified, 2..3),
4708            //TODO: Define better when and where removed hunks show up at range extremities
4709            (DiffHunkStatus::Removed, 6..6),
4710            (DiffHunkStatus::Removed, 8..8),
4711            (DiffHunkStatus::Added, 10..11),
4712        ];
4713
4714        assert_eq!(
4715            snapshot
4716                .git_diff_hunks_in_range(0..12)
4717                .map(|hunk| (hunk.status(), hunk.buffer_range))
4718                .collect::<Vec<_>>(),
4719            &expected,
4720        );
4721
4722        assert_eq!(
4723            snapshot
4724                .git_diff_hunks_in_range_rev(0..12)
4725                .map(|hunk| (hunk.status(), hunk.buffer_range))
4726                .collect::<Vec<_>>(),
4727            expected
4728                .iter()
4729                .rev()
4730                .cloned()
4731                .collect::<Vec<_>>()
4732                .as_slice(),
4733        );
4734    }
4735
4736    #[gpui::test(iterations = 100)]
4737    fn test_random_multibuffer(cx: &mut AppContext, mut rng: StdRng) {
4738        let operations = env::var("OPERATIONS")
4739            .map(|i| i.parse().expect("invalid `OPERATIONS` variable"))
4740            .unwrap_or(10);
4741
4742        let mut buffers: Vec<ModelHandle<Buffer>> = Vec::new();
4743        let multibuffer = cx.add_model(|_| MultiBuffer::new(0));
4744        let mut excerpt_ids = Vec::<ExcerptId>::new();
4745        let mut expected_excerpts = Vec::<(ModelHandle<Buffer>, Range<text::Anchor>)>::new();
4746        let mut anchors = Vec::new();
4747        let mut old_versions = Vec::new();
4748
4749        for _ in 0..operations {
4750            match rng.gen_range(0..100) {
4751                0..=19 if !buffers.is_empty() => {
4752                    let buffer = buffers.choose(&mut rng).unwrap();
4753                    buffer.update(cx, |buf, cx| buf.randomly_edit(&mut rng, 5, cx));
4754                }
4755                20..=29 if !expected_excerpts.is_empty() => {
4756                    let mut ids_to_remove = vec![];
4757                    for _ in 0..rng.gen_range(1..=3) {
4758                        if expected_excerpts.is_empty() {
4759                            break;
4760                        }
4761
4762                        let ix = rng.gen_range(0..expected_excerpts.len());
4763                        ids_to_remove.push(excerpt_ids.remove(ix));
4764                        let (buffer, range) = expected_excerpts.remove(ix);
4765                        let buffer = buffer.read(cx);
4766                        log::info!(
4767                            "Removing excerpt {}: {:?}",
4768                            ix,
4769                            buffer
4770                                .text_for_range(range.to_offset(buffer))
4771                                .collect::<String>(),
4772                        );
4773                    }
4774                    let snapshot = multibuffer.read(cx).read(cx);
4775                    ids_to_remove.sort_unstable_by(|a, b| a.cmp(&b, &snapshot));
4776                    drop(snapshot);
4777                    multibuffer.update(cx, |multibuffer, cx| {
4778                        multibuffer.remove_excerpts(ids_to_remove, cx)
4779                    });
4780                }
4781                30..=39 if !expected_excerpts.is_empty() => {
4782                    let multibuffer = multibuffer.read(cx).read(cx);
4783                    let offset =
4784                        multibuffer.clip_offset(rng.gen_range(0..=multibuffer.len()), Bias::Left);
4785                    let bias = if rng.gen() { Bias::Left } else { Bias::Right };
4786                    log::info!("Creating anchor at {} with bias {:?}", offset, bias);
4787                    anchors.push(multibuffer.anchor_at(offset, bias));
4788                    anchors.sort_by(|a, b| a.cmp(b, &multibuffer));
4789                }
4790                40..=44 if !anchors.is_empty() => {
4791                    let multibuffer = multibuffer.read(cx).read(cx);
4792                    let prev_len = anchors.len();
4793                    anchors = multibuffer
4794                        .refresh_anchors(&anchors)
4795                        .into_iter()
4796                        .map(|a| a.1)
4797                        .collect();
4798
4799                    // Ensure the newly-refreshed anchors point to a valid excerpt and don't
4800                    // overshoot its boundaries.
4801                    assert_eq!(anchors.len(), prev_len);
4802                    for anchor in &anchors {
4803                        if anchor.excerpt_id == ExcerptId::min()
4804                            || anchor.excerpt_id == ExcerptId::max()
4805                        {
4806                            continue;
4807                        }
4808
4809                        let excerpt = multibuffer.excerpt(anchor.excerpt_id).unwrap();
4810                        assert_eq!(excerpt.id, anchor.excerpt_id);
4811                        assert!(excerpt.contains(anchor));
4812                    }
4813                }
4814                _ => {
4815                    let buffer_handle = if buffers.is_empty() || rng.gen_bool(0.4) {
4816                        let base_text = util::RandomCharIter::new(&mut rng)
4817                            .take(10)
4818                            .collect::<String>();
4819                        buffers.push(cx.add_model(|cx| Buffer::new(0, base_text, cx)));
4820                        buffers.last().unwrap()
4821                    } else {
4822                        buffers.choose(&mut rng).unwrap()
4823                    };
4824
4825                    let buffer = buffer_handle.read(cx);
4826                    let end_ix = buffer.clip_offset(rng.gen_range(0..=buffer.len()), Bias::Right);
4827                    let start_ix = buffer.clip_offset(rng.gen_range(0..=end_ix), Bias::Left);
4828                    let anchor_range = buffer.anchor_before(start_ix)..buffer.anchor_after(end_ix);
4829                    let prev_excerpt_ix = rng.gen_range(0..=expected_excerpts.len());
4830                    let prev_excerpt_id = excerpt_ids
4831                        .get(prev_excerpt_ix)
4832                        .cloned()
4833                        .unwrap_or_else(ExcerptId::max);
4834                    let excerpt_ix = (prev_excerpt_ix + 1).min(expected_excerpts.len());
4835
4836                    log::info!(
4837                        "Inserting excerpt at {} of {} for buffer {}: {:?}[{:?}] = {:?}",
4838                        excerpt_ix,
4839                        expected_excerpts.len(),
4840                        buffer_handle.read(cx).remote_id(),
4841                        buffer.text(),
4842                        start_ix..end_ix,
4843                        &buffer.text()[start_ix..end_ix]
4844                    );
4845
4846                    let excerpt_id = multibuffer.update(cx, |multibuffer, cx| {
4847                        multibuffer
4848                            .insert_excerpts_after(
4849                                prev_excerpt_id,
4850                                buffer_handle.clone(),
4851                                [ExcerptRange {
4852                                    context: start_ix..end_ix,
4853                                    primary: None,
4854                                }],
4855                                cx,
4856                            )
4857                            .pop()
4858                            .unwrap()
4859                    });
4860
4861                    excerpt_ids.insert(excerpt_ix, excerpt_id);
4862                    expected_excerpts.insert(excerpt_ix, (buffer_handle.clone(), anchor_range));
4863                }
4864            }
4865
4866            if rng.gen_bool(0.3) {
4867                multibuffer.update(cx, |multibuffer, cx| {
4868                    old_versions.push((multibuffer.snapshot(cx), multibuffer.subscribe()));
4869                })
4870            }
4871
4872            let snapshot = multibuffer.read(cx).snapshot(cx);
4873
4874            let mut excerpt_starts = Vec::new();
4875            let mut expected_text = String::new();
4876            let mut expected_buffer_rows = Vec::new();
4877            for (buffer, range) in &expected_excerpts {
4878                let buffer = buffer.read(cx);
4879                let buffer_range = range.to_offset(buffer);
4880
4881                excerpt_starts.push(TextSummary::from(expected_text.as_str()));
4882                expected_text.extend(buffer.text_for_range(buffer_range.clone()));
4883                expected_text.push('\n');
4884
4885                let buffer_row_range = buffer.offset_to_point(buffer_range.start).row
4886                    ..=buffer.offset_to_point(buffer_range.end).row;
4887                for row in buffer_row_range {
4888                    expected_buffer_rows.push(Some(row));
4889                }
4890            }
4891            // Remove final trailing newline.
4892            if !expected_excerpts.is_empty() {
4893                expected_text.pop();
4894            }
4895
4896            // Always report one buffer row
4897            if expected_buffer_rows.is_empty() {
4898                expected_buffer_rows.push(Some(0));
4899            }
4900
4901            assert_eq!(snapshot.text(), expected_text);
4902            log::info!("MultiBuffer text: {:?}", expected_text);
4903
4904            assert_eq!(
4905                snapshot.buffer_rows(0).collect::<Vec<_>>(),
4906                expected_buffer_rows,
4907            );
4908
4909            for _ in 0..5 {
4910                let start_row = rng.gen_range(0..=expected_buffer_rows.len());
4911                assert_eq!(
4912                    snapshot.buffer_rows(start_row as u32).collect::<Vec<_>>(),
4913                    &expected_buffer_rows[start_row..],
4914                    "buffer_rows({})",
4915                    start_row
4916                );
4917            }
4918
4919            assert_eq!(
4920                snapshot.max_buffer_row(),
4921                expected_buffer_rows.into_iter().flatten().max().unwrap()
4922            );
4923
4924            let mut excerpt_starts = excerpt_starts.into_iter();
4925            for (buffer, range) in &expected_excerpts {
4926                let buffer = buffer.read(cx);
4927                let buffer_id = buffer.remote_id();
4928                let buffer_range = range.to_offset(buffer);
4929                let buffer_start_point = buffer.offset_to_point(buffer_range.start);
4930                let buffer_start_point_utf16 =
4931                    buffer.text_summary_for_range::<PointUtf16, _>(0..buffer_range.start);
4932
4933                let excerpt_start = excerpt_starts.next().unwrap();
4934                let mut offset = excerpt_start.len;
4935                let mut buffer_offset = buffer_range.start;
4936                let mut point = excerpt_start.lines;
4937                let mut buffer_point = buffer_start_point;
4938                let mut point_utf16 = excerpt_start.lines_utf16();
4939                let mut buffer_point_utf16 = buffer_start_point_utf16;
4940                for ch in buffer
4941                    .snapshot()
4942                    .chunks(buffer_range.clone(), false)
4943                    .flat_map(|c| c.text.chars())
4944                {
4945                    for _ in 0..ch.len_utf8() {
4946                        let left_offset = snapshot.clip_offset(offset, Bias::Left);
4947                        let right_offset = snapshot.clip_offset(offset, Bias::Right);
4948                        let buffer_left_offset = buffer.clip_offset(buffer_offset, Bias::Left);
4949                        let buffer_right_offset = buffer.clip_offset(buffer_offset, Bias::Right);
4950                        assert_eq!(
4951                            left_offset,
4952                            excerpt_start.len + (buffer_left_offset - buffer_range.start),
4953                            "clip_offset({:?}, Left). buffer: {:?}, buffer offset: {:?}",
4954                            offset,
4955                            buffer_id,
4956                            buffer_offset,
4957                        );
4958                        assert_eq!(
4959                            right_offset,
4960                            excerpt_start.len + (buffer_right_offset - buffer_range.start),
4961                            "clip_offset({:?}, Right). buffer: {:?}, buffer offset: {:?}",
4962                            offset,
4963                            buffer_id,
4964                            buffer_offset,
4965                        );
4966
4967                        let left_point = snapshot.clip_point(point, Bias::Left);
4968                        let right_point = snapshot.clip_point(point, Bias::Right);
4969                        let buffer_left_point = buffer.clip_point(buffer_point, Bias::Left);
4970                        let buffer_right_point = buffer.clip_point(buffer_point, Bias::Right);
4971                        assert_eq!(
4972                            left_point,
4973                            excerpt_start.lines + (buffer_left_point - buffer_start_point),
4974                            "clip_point({:?}, Left). buffer: {:?}, buffer point: {:?}",
4975                            point,
4976                            buffer_id,
4977                            buffer_point,
4978                        );
4979                        assert_eq!(
4980                            right_point,
4981                            excerpt_start.lines + (buffer_right_point - buffer_start_point),
4982                            "clip_point({:?}, Right). buffer: {:?}, buffer point: {:?}",
4983                            point,
4984                            buffer_id,
4985                            buffer_point,
4986                        );
4987
4988                        assert_eq!(
4989                            snapshot.point_to_offset(left_point),
4990                            left_offset,
4991                            "point_to_offset({:?})",
4992                            left_point,
4993                        );
4994                        assert_eq!(
4995                            snapshot.offset_to_point(left_offset),
4996                            left_point,
4997                            "offset_to_point({:?})",
4998                            left_offset,
4999                        );
5000
5001                        offset += 1;
5002                        buffer_offset += 1;
5003                        if ch == '\n' {
5004                            point += Point::new(1, 0);
5005                            buffer_point += Point::new(1, 0);
5006                        } else {
5007                            point += Point::new(0, 1);
5008                            buffer_point += Point::new(0, 1);
5009                        }
5010                    }
5011
5012                    for _ in 0..ch.len_utf16() {
5013                        let left_point_utf16 =
5014                            snapshot.clip_point_utf16(Unclipped(point_utf16), Bias::Left);
5015                        let right_point_utf16 =
5016                            snapshot.clip_point_utf16(Unclipped(point_utf16), Bias::Right);
5017                        let buffer_left_point_utf16 =
5018                            buffer.clip_point_utf16(Unclipped(buffer_point_utf16), Bias::Left);
5019                        let buffer_right_point_utf16 =
5020                            buffer.clip_point_utf16(Unclipped(buffer_point_utf16), Bias::Right);
5021                        assert_eq!(
5022                            left_point_utf16,
5023                            excerpt_start.lines_utf16()
5024                                + (buffer_left_point_utf16 - buffer_start_point_utf16),
5025                            "clip_point_utf16({:?}, Left). buffer: {:?}, buffer point_utf16: {:?}",
5026                            point_utf16,
5027                            buffer_id,
5028                            buffer_point_utf16,
5029                        );
5030                        assert_eq!(
5031                            right_point_utf16,
5032                            excerpt_start.lines_utf16()
5033                                + (buffer_right_point_utf16 - buffer_start_point_utf16),
5034                            "clip_point_utf16({:?}, Right). buffer: {:?}, buffer point_utf16: {:?}",
5035                            point_utf16,
5036                            buffer_id,
5037                            buffer_point_utf16,
5038                        );
5039
5040                        if ch == '\n' {
5041                            point_utf16 += PointUtf16::new(1, 0);
5042                            buffer_point_utf16 += PointUtf16::new(1, 0);
5043                        } else {
5044                            point_utf16 += PointUtf16::new(0, 1);
5045                            buffer_point_utf16 += PointUtf16::new(0, 1);
5046                        }
5047                    }
5048                }
5049            }
5050
5051            for (row, line) in expected_text.split('\n').enumerate() {
5052                assert_eq!(
5053                    snapshot.line_len(row as u32),
5054                    line.len() as u32,
5055                    "line_len({}).",
5056                    row
5057                );
5058            }
5059
5060            let text_rope = Rope::from(expected_text.as_str());
5061            for _ in 0..10 {
5062                let end_ix = text_rope.clip_offset(rng.gen_range(0..=text_rope.len()), Bias::Right);
5063                let start_ix = text_rope.clip_offset(rng.gen_range(0..=end_ix), Bias::Left);
5064
5065                let text_for_range = snapshot
5066                    .text_for_range(start_ix..end_ix)
5067                    .collect::<String>();
5068                assert_eq!(
5069                    text_for_range,
5070                    &expected_text[start_ix..end_ix],
5071                    "incorrect text for range {:?}",
5072                    start_ix..end_ix
5073                );
5074
5075                let excerpted_buffer_ranges = multibuffer
5076                    .read(cx)
5077                    .range_to_buffer_ranges(start_ix..end_ix, cx);
5078                let excerpted_buffers_text = excerpted_buffer_ranges
5079                    .iter()
5080                    .map(|(buffer, buffer_range)| {
5081                        buffer
5082                            .read(cx)
5083                            .text_for_range(buffer_range.clone())
5084                            .collect::<String>()
5085                    })
5086                    .collect::<Vec<_>>()
5087                    .join("\n");
5088                assert_eq!(excerpted_buffers_text, text_for_range);
5089                if !expected_excerpts.is_empty() {
5090                    assert!(!excerpted_buffer_ranges.is_empty());
5091                }
5092
5093                let expected_summary = TextSummary::from(&expected_text[start_ix..end_ix]);
5094                assert_eq!(
5095                    snapshot.text_summary_for_range::<TextSummary, _>(start_ix..end_ix),
5096                    expected_summary,
5097                    "incorrect summary for range {:?}",
5098                    start_ix..end_ix
5099                );
5100            }
5101
5102            // Anchor resolution
5103            let summaries = snapshot.summaries_for_anchors::<usize, _>(&anchors);
5104            assert_eq!(anchors.len(), summaries.len());
5105            for (anchor, resolved_offset) in anchors.iter().zip(summaries) {
5106                assert!(resolved_offset <= snapshot.len());
5107                assert_eq!(
5108                    snapshot.summary_for_anchor::<usize>(anchor),
5109                    resolved_offset
5110                );
5111            }
5112
5113            for _ in 0..10 {
5114                let end_ix = text_rope.clip_offset(rng.gen_range(0..=text_rope.len()), Bias::Right);
5115                assert_eq!(
5116                    snapshot.reversed_chars_at(end_ix).collect::<String>(),
5117                    expected_text[..end_ix].chars().rev().collect::<String>(),
5118                );
5119            }
5120
5121            for _ in 0..10 {
5122                let end_ix = rng.gen_range(0..=text_rope.len());
5123                let start_ix = rng.gen_range(0..=end_ix);
5124                assert_eq!(
5125                    snapshot
5126                        .bytes_in_range(start_ix..end_ix)
5127                        .flatten()
5128                        .copied()
5129                        .collect::<Vec<_>>(),
5130                    expected_text.as_bytes()[start_ix..end_ix].to_vec(),
5131                    "bytes_in_range({:?})",
5132                    start_ix..end_ix,
5133                );
5134            }
5135        }
5136
5137        let snapshot = multibuffer.read(cx).snapshot(cx);
5138        for (old_snapshot, subscription) in old_versions {
5139            let edits = subscription.consume().into_inner();
5140
5141            log::info!(
5142                "applying subscription edits to old text: {:?}: {:?}",
5143                old_snapshot.text(),
5144                edits,
5145            );
5146
5147            let mut text = old_snapshot.text();
5148            for edit in edits {
5149                let new_text: String = snapshot.text_for_range(edit.new.clone()).collect();
5150                text.replace_range(edit.new.start..edit.new.start + edit.old.len(), &new_text);
5151            }
5152            assert_eq!(text.to_string(), snapshot.text());
5153        }
5154    }
5155
5156    #[gpui::test]
5157    fn test_history(cx: &mut AppContext) {
5158        cx.set_global(SettingsStore::test(cx));
5159
5160        let buffer_1 = cx.add_model(|cx| Buffer::new(0, "1234", cx));
5161        let buffer_2 = cx.add_model(|cx| Buffer::new(0, "5678", cx));
5162        let multibuffer = cx.add_model(|_| MultiBuffer::new(0));
5163        let group_interval = multibuffer.read(cx).history.group_interval;
5164        multibuffer.update(cx, |multibuffer, cx| {
5165            multibuffer.push_excerpts(
5166                buffer_1.clone(),
5167                [ExcerptRange {
5168                    context: 0..buffer_1.read(cx).len(),
5169                    primary: None,
5170                }],
5171                cx,
5172            );
5173            multibuffer.push_excerpts(
5174                buffer_2.clone(),
5175                [ExcerptRange {
5176                    context: 0..buffer_2.read(cx).len(),
5177                    primary: None,
5178                }],
5179                cx,
5180            );
5181        });
5182
5183        let mut now = Instant::now();
5184
5185        multibuffer.update(cx, |multibuffer, cx| {
5186            let transaction_1 = multibuffer.start_transaction_at(now, cx).unwrap();
5187            multibuffer.edit(
5188                [
5189                    (Point::new(0, 0)..Point::new(0, 0), "A"),
5190                    (Point::new(1, 0)..Point::new(1, 0), "A"),
5191                ],
5192                None,
5193                cx,
5194            );
5195            multibuffer.edit(
5196                [
5197                    (Point::new(0, 1)..Point::new(0, 1), "B"),
5198                    (Point::new(1, 1)..Point::new(1, 1), "B"),
5199                ],
5200                None,
5201                cx,
5202            );
5203            multibuffer.end_transaction_at(now, cx);
5204            assert_eq!(multibuffer.read(cx).text(), "AB1234\nAB5678");
5205
5206            // Edit buffer 1 through the multibuffer
5207            now += 2 * group_interval;
5208            multibuffer.start_transaction_at(now, cx);
5209            multibuffer.edit([(2..2, "C")], None, cx);
5210            multibuffer.end_transaction_at(now, cx);
5211            assert_eq!(multibuffer.read(cx).text(), "ABC1234\nAB5678");
5212
5213            // Edit buffer 1 independently
5214            buffer_1.update(cx, |buffer_1, cx| {
5215                buffer_1.start_transaction_at(now);
5216                buffer_1.edit([(3..3, "D")], None, cx);
5217                buffer_1.end_transaction_at(now, cx);
5218
5219                now += 2 * group_interval;
5220                buffer_1.start_transaction_at(now);
5221                buffer_1.edit([(4..4, "E")], None, cx);
5222                buffer_1.end_transaction_at(now, cx);
5223            });
5224            assert_eq!(multibuffer.read(cx).text(), "ABCDE1234\nAB5678");
5225
5226            // An undo in the multibuffer undoes the multibuffer transaction
5227            // and also any individual buffer edits that have occured since
5228            // that transaction.
5229            multibuffer.undo(cx);
5230            assert_eq!(multibuffer.read(cx).text(), "AB1234\nAB5678");
5231
5232            multibuffer.undo(cx);
5233            assert_eq!(multibuffer.read(cx).text(), "1234\n5678");
5234
5235            multibuffer.redo(cx);
5236            assert_eq!(multibuffer.read(cx).text(), "AB1234\nAB5678");
5237
5238            multibuffer.redo(cx);
5239            assert_eq!(multibuffer.read(cx).text(), "ABCDE1234\nAB5678");
5240
5241            // Undo buffer 2 independently.
5242            buffer_2.update(cx, |buffer_2, cx| buffer_2.undo(cx));
5243            assert_eq!(multibuffer.read(cx).text(), "ABCDE1234\n5678");
5244
5245            // An undo in the multibuffer undoes the components of the
5246            // the last multibuffer transaction that are not already undone.
5247            multibuffer.undo(cx);
5248            assert_eq!(multibuffer.read(cx).text(), "AB1234\n5678");
5249
5250            multibuffer.undo(cx);
5251            assert_eq!(multibuffer.read(cx).text(), "1234\n5678");
5252
5253            multibuffer.redo(cx);
5254            assert_eq!(multibuffer.read(cx).text(), "AB1234\nAB5678");
5255
5256            buffer_1.update(cx, |buffer_1, cx| buffer_1.redo(cx));
5257            assert_eq!(multibuffer.read(cx).text(), "ABCD1234\nAB5678");
5258
5259            // Redo stack gets cleared after an edit.
5260            now += 2 * group_interval;
5261            multibuffer.start_transaction_at(now, cx);
5262            multibuffer.edit([(0..0, "X")], None, cx);
5263            multibuffer.end_transaction_at(now, cx);
5264            assert_eq!(multibuffer.read(cx).text(), "XABCD1234\nAB5678");
5265            multibuffer.redo(cx);
5266            assert_eq!(multibuffer.read(cx).text(), "XABCD1234\nAB5678");
5267            multibuffer.undo(cx);
5268            assert_eq!(multibuffer.read(cx).text(), "ABCD1234\nAB5678");
5269            multibuffer.undo(cx);
5270            assert_eq!(multibuffer.read(cx).text(), "1234\n5678");
5271
5272            // Transactions can be grouped manually.
5273            multibuffer.redo(cx);
5274            multibuffer.redo(cx);
5275            assert_eq!(multibuffer.read(cx).text(), "XABCD1234\nAB5678");
5276            multibuffer.group_until_transaction(transaction_1, cx);
5277            multibuffer.undo(cx);
5278            assert_eq!(multibuffer.read(cx).text(), "1234\n5678");
5279            multibuffer.redo(cx);
5280            assert_eq!(multibuffer.read(cx).text(), "XABCD1234\nAB5678");
5281        });
5282    }
5283}