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