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