multi_buffer.rs

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