multi_buffer.rs

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