multi_buffer.rs

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