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 futures::StreamExt;
3680    use gpui::{MutableAppContext, TestAppContext};
3681    use language::{Buffer, Rope};
3682    use rand::prelude::*;
3683    use settings::Settings;
3684    use std::{env, rc::Rc};
3685    use unindent::Unindent;
3686
3687    use util::test::sample_text;
3688
3689    #[gpui::test]
3690    fn test_singleton(cx: &mut MutableAppContext) {
3691        let buffer = cx.add_model(|cx| Buffer::new(0, sample_text(6, 6, 'a'), cx));
3692        let multibuffer = cx.add_model(|cx| MultiBuffer::singleton(buffer.clone(), cx));
3693
3694        let snapshot = multibuffer.read(cx).snapshot(cx);
3695        assert_eq!(snapshot.text(), buffer.read(cx).text());
3696
3697        assert_eq!(
3698            snapshot.buffer_rows(0).collect::<Vec<_>>(),
3699            (0..buffer.read(cx).row_count())
3700                .map(Some)
3701                .collect::<Vec<_>>()
3702        );
3703
3704        buffer.update(cx, |buffer, cx| buffer.edit([(1..3, "XXX\n")], None, cx));
3705        let snapshot = multibuffer.read(cx).snapshot(cx);
3706
3707        assert_eq!(snapshot.text(), buffer.read(cx).text());
3708        assert_eq!(
3709            snapshot.buffer_rows(0).collect::<Vec<_>>(),
3710            (0..buffer.read(cx).row_count())
3711                .map(Some)
3712                .collect::<Vec<_>>()
3713        );
3714    }
3715
3716    #[gpui::test]
3717    fn test_remote(cx: &mut MutableAppContext) {
3718        let host_buffer = cx.add_model(|cx| Buffer::new(0, "a", cx));
3719        let guest_buffer = cx.add_model(|cx| {
3720            let state = host_buffer.read(cx).to_proto();
3721            let ops = cx
3722                .background()
3723                .block(host_buffer.read(cx).serialize_ops(None, cx));
3724            let mut buffer = Buffer::from_proto(1, state, None).unwrap();
3725            buffer
3726                .apply_ops(
3727                    ops.into_iter()
3728                        .map(|op| language::proto::deserialize_operation(op).unwrap()),
3729                    cx,
3730                )
3731                .unwrap();
3732            buffer
3733        });
3734        let multibuffer = cx.add_model(|cx| MultiBuffer::singleton(guest_buffer.clone(), cx));
3735        let snapshot = multibuffer.read(cx).snapshot(cx);
3736        assert_eq!(snapshot.text(), "a");
3737
3738        guest_buffer.update(cx, |buffer, cx| buffer.edit([(1..1, "b")], None, cx));
3739        let snapshot = multibuffer.read(cx).snapshot(cx);
3740        assert_eq!(snapshot.text(), "ab");
3741
3742        guest_buffer.update(cx, |buffer, cx| buffer.edit([(2..2, "c")], None, cx));
3743        let snapshot = multibuffer.read(cx).snapshot(cx);
3744        assert_eq!(snapshot.text(), "abc");
3745    }
3746
3747    #[gpui::test]
3748    fn test_excerpt_boundaries_and_clipping(cx: &mut MutableAppContext) {
3749        let buffer_1 = cx.add_model(|cx| Buffer::new(0, sample_text(6, 6, 'a'), cx));
3750        let buffer_2 = cx.add_model(|cx| Buffer::new(0, sample_text(6, 6, 'g'), cx));
3751        let multibuffer = cx.add_model(|_| MultiBuffer::new(0));
3752
3753        let events = Rc::new(RefCell::new(Vec::<Event>::new()));
3754        multibuffer.update(cx, |_, cx| {
3755            let events = events.clone();
3756            cx.subscribe(&multibuffer, move |_, _, event, _| {
3757                if let Event::Edited = event {
3758                    events.borrow_mut().push(event.clone())
3759                }
3760            })
3761            .detach();
3762        });
3763
3764        let subscription = multibuffer.update(cx, |multibuffer, cx| {
3765            let subscription = multibuffer.subscribe();
3766            multibuffer.push_excerpts(
3767                buffer_1.clone(),
3768                [ExcerptRange {
3769                    context: Point::new(1, 2)..Point::new(2, 5),
3770                    primary: None,
3771                }],
3772                cx,
3773            );
3774            assert_eq!(
3775                subscription.consume().into_inner(),
3776                [Edit {
3777                    old: 0..0,
3778                    new: 0..10
3779                }]
3780            );
3781
3782            multibuffer.push_excerpts(
3783                buffer_1.clone(),
3784                [ExcerptRange {
3785                    context: Point::new(3, 3)..Point::new(4, 4),
3786                    primary: None,
3787                }],
3788                cx,
3789            );
3790            multibuffer.push_excerpts(
3791                buffer_2.clone(),
3792                [ExcerptRange {
3793                    context: Point::new(3, 1)..Point::new(3, 3),
3794                    primary: None,
3795                }],
3796                cx,
3797            );
3798            assert_eq!(
3799                subscription.consume().into_inner(),
3800                [Edit {
3801                    old: 10..10,
3802                    new: 10..22
3803                }]
3804            );
3805
3806            subscription
3807        });
3808
3809        // Adding excerpts emits an edited event.
3810        assert_eq!(
3811            events.borrow().as_slice(),
3812            &[Event::Edited, Event::Edited, Event::Edited]
3813        );
3814
3815        let snapshot = multibuffer.read(cx).snapshot(cx);
3816        assert_eq!(
3817            snapshot.text(),
3818            concat!(
3819                "bbbb\n",  // Preserve newlines
3820                "ccccc\n", //
3821                "ddd\n",   //
3822                "eeee\n",  //
3823                "jj"       //
3824            )
3825        );
3826        assert_eq!(
3827            snapshot.buffer_rows(0).collect::<Vec<_>>(),
3828            [Some(1), Some(2), Some(3), Some(4), Some(3)]
3829        );
3830        assert_eq!(
3831            snapshot.buffer_rows(2).collect::<Vec<_>>(),
3832            [Some(3), Some(4), Some(3)]
3833        );
3834        assert_eq!(snapshot.buffer_rows(4).collect::<Vec<_>>(), [Some(3)]);
3835        assert_eq!(snapshot.buffer_rows(5).collect::<Vec<_>>(), []);
3836
3837        assert_eq!(
3838            boundaries_in_range(Point::new(0, 0)..Point::new(4, 2), &snapshot),
3839            &[
3840                (0, "bbbb\nccccc".to_string(), true),
3841                (2, "ddd\neeee".to_string(), false),
3842                (4, "jj".to_string(), true),
3843            ]
3844        );
3845        assert_eq!(
3846            boundaries_in_range(Point::new(0, 0)..Point::new(2, 0), &snapshot),
3847            &[(0, "bbbb\nccccc".to_string(), true)]
3848        );
3849        assert_eq!(
3850            boundaries_in_range(Point::new(1, 0)..Point::new(1, 5), &snapshot),
3851            &[]
3852        );
3853        assert_eq!(
3854            boundaries_in_range(Point::new(1, 0)..Point::new(2, 0), &snapshot),
3855            &[]
3856        );
3857        assert_eq!(
3858            boundaries_in_range(Point::new(1, 0)..Point::new(4, 0), &snapshot),
3859            &[(2, "ddd\neeee".to_string(), false)]
3860        );
3861        assert_eq!(
3862            boundaries_in_range(Point::new(1, 0)..Point::new(4, 0), &snapshot),
3863            &[(2, "ddd\neeee".to_string(), false)]
3864        );
3865        assert_eq!(
3866            boundaries_in_range(Point::new(2, 0)..Point::new(3, 0), &snapshot),
3867            &[(2, "ddd\neeee".to_string(), false)]
3868        );
3869        assert_eq!(
3870            boundaries_in_range(Point::new(4, 0)..Point::new(4, 2), &snapshot),
3871            &[(4, "jj".to_string(), true)]
3872        );
3873        assert_eq!(
3874            boundaries_in_range(Point::new(4, 2)..Point::new(4, 2), &snapshot),
3875            &[]
3876        );
3877
3878        buffer_1.update(cx, |buffer, cx| {
3879            let text = "\n";
3880            buffer.edit(
3881                [
3882                    (Point::new(0, 0)..Point::new(0, 0), text),
3883                    (Point::new(2, 1)..Point::new(2, 3), text),
3884                ],
3885                None,
3886                cx,
3887            );
3888        });
3889
3890        let snapshot = multibuffer.read(cx).snapshot(cx);
3891        assert_eq!(
3892            snapshot.text(),
3893            concat!(
3894                "bbbb\n", // Preserve newlines
3895                "c\n",    //
3896                "cc\n",   //
3897                "ddd\n",  //
3898                "eeee\n", //
3899                "jj"      //
3900            )
3901        );
3902
3903        assert_eq!(
3904            subscription.consume().into_inner(),
3905            [Edit {
3906                old: 6..8,
3907                new: 6..7
3908            }]
3909        );
3910
3911        let snapshot = multibuffer.read(cx).snapshot(cx);
3912        assert_eq!(
3913            snapshot.clip_point(Point::new(0, 5), Bias::Left),
3914            Point::new(0, 4)
3915        );
3916        assert_eq!(
3917            snapshot.clip_point(Point::new(0, 5), Bias::Right),
3918            Point::new(0, 4)
3919        );
3920        assert_eq!(
3921            snapshot.clip_point(Point::new(5, 1), Bias::Right),
3922            Point::new(5, 1)
3923        );
3924        assert_eq!(
3925            snapshot.clip_point(Point::new(5, 2), Bias::Right),
3926            Point::new(5, 2)
3927        );
3928        assert_eq!(
3929            snapshot.clip_point(Point::new(5, 3), Bias::Right),
3930            Point::new(5, 2)
3931        );
3932
3933        let snapshot = multibuffer.update(cx, |multibuffer, cx| {
3934            let (buffer_2_excerpt_id, _) =
3935                multibuffer.excerpts_for_buffer(&buffer_2, cx)[0].clone();
3936            multibuffer.remove_excerpts([buffer_2_excerpt_id], cx);
3937            multibuffer.snapshot(cx)
3938        });
3939
3940        assert_eq!(
3941            snapshot.text(),
3942            concat!(
3943                "bbbb\n", // Preserve newlines
3944                "c\n",    //
3945                "cc\n",   //
3946                "ddd\n",  //
3947                "eeee",   //
3948            )
3949        );
3950
3951        fn boundaries_in_range(
3952            range: Range<Point>,
3953            snapshot: &MultiBufferSnapshot,
3954        ) -> Vec<(u32, String, bool)> {
3955            snapshot
3956                .excerpt_boundaries_in_range(range)
3957                .map(|boundary| {
3958                    (
3959                        boundary.row,
3960                        boundary
3961                            .buffer
3962                            .text_for_range(boundary.range.context)
3963                            .collect::<String>(),
3964                        boundary.starts_new_buffer,
3965                    )
3966                })
3967                .collect::<Vec<_>>()
3968        }
3969    }
3970
3971    #[gpui::test]
3972    fn test_excerpt_events(cx: &mut MutableAppContext) {
3973        let buffer_1 = cx.add_model(|cx| Buffer::new(0, sample_text(10, 3, 'a'), cx));
3974        let buffer_2 = cx.add_model(|cx| Buffer::new(0, sample_text(10, 3, 'm'), cx));
3975
3976        let leader_multibuffer = cx.add_model(|_| MultiBuffer::new(0));
3977        let follower_multibuffer = cx.add_model(|_| MultiBuffer::new(0));
3978
3979        follower_multibuffer.update(cx, |_, cx| {
3980            cx.subscribe(&leader_multibuffer, |follower, _, event, cx| {
3981                match event.clone() {
3982                    Event::ExcerptsAdded {
3983                        buffer,
3984                        predecessor,
3985                        excerpts,
3986                    } => follower.insert_excerpts_with_ids_after(predecessor, buffer, excerpts, cx),
3987                    Event::ExcerptsRemoved { ids } => follower.remove_excerpts(ids, cx),
3988                    _ => {}
3989                }
3990            })
3991            .detach();
3992        });
3993
3994        leader_multibuffer.update(cx, |leader, cx| {
3995            leader.push_excerpts(
3996                buffer_1.clone(),
3997                [
3998                    ExcerptRange {
3999                        context: 0..8,
4000                        primary: None,
4001                    },
4002                    ExcerptRange {
4003                        context: 12..16,
4004                        primary: None,
4005                    },
4006                ],
4007                cx,
4008            );
4009            leader.insert_excerpts_after(
4010                leader.excerpt_ids()[0],
4011                buffer_2.clone(),
4012                [
4013                    ExcerptRange {
4014                        context: 0..5,
4015                        primary: None,
4016                    },
4017                    ExcerptRange {
4018                        context: 10..15,
4019                        primary: None,
4020                    },
4021                ],
4022                cx,
4023            )
4024        });
4025        assert_eq!(
4026            leader_multibuffer.read(cx).snapshot(cx).text(),
4027            follower_multibuffer.read(cx).snapshot(cx).text(),
4028        );
4029
4030        leader_multibuffer.update(cx, |leader, cx| {
4031            let excerpt_ids = leader.excerpt_ids();
4032            leader.remove_excerpts([excerpt_ids[1], excerpt_ids[3]], cx);
4033        });
4034        assert_eq!(
4035            leader_multibuffer.read(cx).snapshot(cx).text(),
4036            follower_multibuffer.read(cx).snapshot(cx).text(),
4037        );
4038
4039        leader_multibuffer.update(cx, |leader, cx| {
4040            leader.clear(cx);
4041        });
4042        assert_eq!(
4043            leader_multibuffer.read(cx).snapshot(cx).text(),
4044            follower_multibuffer.read(cx).snapshot(cx).text(),
4045        );
4046    }
4047
4048    #[gpui::test]
4049    fn test_push_excerpts_with_context_lines(cx: &mut MutableAppContext) {
4050        let buffer = cx.add_model(|cx| Buffer::new(0, sample_text(20, 3, 'a'), cx));
4051        let multibuffer = cx.add_model(|_| MultiBuffer::new(0));
4052        let anchor_ranges = multibuffer.update(cx, |multibuffer, cx| {
4053            multibuffer.push_excerpts_with_context_lines(
4054                buffer.clone(),
4055                vec![
4056                    Point::new(3, 2)..Point::new(4, 2),
4057                    Point::new(7, 1)..Point::new(7, 3),
4058                    Point::new(15, 0)..Point::new(15, 0),
4059                ],
4060                2,
4061                cx,
4062            )
4063        });
4064
4065        let snapshot = multibuffer.read(cx).snapshot(cx);
4066        assert_eq!(
4067            snapshot.text(),
4068            "bbb\nccc\nddd\neee\nfff\nggg\nhhh\niii\njjj\n\nnnn\nooo\nppp\nqqq\nrrr\n"
4069        );
4070
4071        assert_eq!(
4072            anchor_ranges
4073                .iter()
4074                .map(|range| range.to_point(&snapshot))
4075                .collect::<Vec<_>>(),
4076            vec![
4077                Point::new(2, 2)..Point::new(3, 2),
4078                Point::new(6, 1)..Point::new(6, 3),
4079                Point::new(12, 0)..Point::new(12, 0)
4080            ]
4081        );
4082    }
4083
4084    #[gpui::test]
4085    async fn test_stream_excerpts_with_context_lines(cx: &mut TestAppContext) {
4086        let buffer = cx.add_model(|cx| Buffer::new(0, sample_text(20, 3, 'a'), cx));
4087        let multibuffer = cx.add_model(|_| MultiBuffer::new(0));
4088        let (task, anchor_ranges) = multibuffer.update(cx, |multibuffer, cx| {
4089            let snapshot = buffer.read(cx);
4090            let ranges = vec![
4091                snapshot.anchor_before(Point::new(3, 2))..snapshot.anchor_before(Point::new(4, 2)),
4092                snapshot.anchor_before(Point::new(7, 1))..snapshot.anchor_before(Point::new(7, 3)),
4093                snapshot.anchor_before(Point::new(15, 0))
4094                    ..snapshot.anchor_before(Point::new(15, 0)),
4095            ];
4096            multibuffer.stream_excerpts_with_context_lines(vec![(buffer.clone(), ranges)], 2, cx)
4097        });
4098
4099        let anchor_ranges = anchor_ranges.collect::<Vec<_>>().await;
4100        // Ensure task is finished when stream completes.
4101        task.await;
4102
4103        let snapshot = multibuffer.read_with(cx, |multibuffer, cx| multibuffer.snapshot(cx));
4104        assert_eq!(
4105            snapshot.text(),
4106            "bbb\nccc\nddd\neee\nfff\nggg\nhhh\niii\njjj\n\nnnn\nooo\nppp\nqqq\nrrr\n"
4107        );
4108
4109        assert_eq!(
4110            anchor_ranges
4111                .iter()
4112                .map(|range| range.to_point(&snapshot))
4113                .collect::<Vec<_>>(),
4114            vec![
4115                Point::new(2, 2)..Point::new(3, 2),
4116                Point::new(6, 1)..Point::new(6, 3),
4117                Point::new(12, 0)..Point::new(12, 0)
4118            ]
4119        );
4120    }
4121
4122    #[gpui::test]
4123    fn test_empty_multibuffer(cx: &mut MutableAppContext) {
4124        let multibuffer = cx.add_model(|_| MultiBuffer::new(0));
4125
4126        let snapshot = multibuffer.read(cx).snapshot(cx);
4127        assert_eq!(snapshot.text(), "");
4128        assert_eq!(snapshot.buffer_rows(0).collect::<Vec<_>>(), &[Some(0)]);
4129        assert_eq!(snapshot.buffer_rows(1).collect::<Vec<_>>(), &[]);
4130    }
4131
4132    #[gpui::test]
4133    fn test_singleton_multibuffer_anchors(cx: &mut MutableAppContext) {
4134        let buffer = cx.add_model(|cx| Buffer::new(0, "abcd", cx));
4135        let multibuffer = cx.add_model(|cx| MultiBuffer::singleton(buffer.clone(), cx));
4136        let old_snapshot = multibuffer.read(cx).snapshot(cx);
4137        buffer.update(cx, |buffer, cx| {
4138            buffer.edit([(0..0, "X")], None, cx);
4139            buffer.edit([(5..5, "Y")], None, cx);
4140        });
4141        let new_snapshot = multibuffer.read(cx).snapshot(cx);
4142
4143        assert_eq!(old_snapshot.text(), "abcd");
4144        assert_eq!(new_snapshot.text(), "XabcdY");
4145
4146        assert_eq!(old_snapshot.anchor_before(0).to_offset(&new_snapshot), 0);
4147        assert_eq!(old_snapshot.anchor_after(0).to_offset(&new_snapshot), 1);
4148        assert_eq!(old_snapshot.anchor_before(4).to_offset(&new_snapshot), 5);
4149        assert_eq!(old_snapshot.anchor_after(4).to_offset(&new_snapshot), 6);
4150    }
4151
4152    #[gpui::test]
4153    fn test_multibuffer_anchors(cx: &mut MutableAppContext) {
4154        let buffer_1 = cx.add_model(|cx| Buffer::new(0, "abcd", cx));
4155        let buffer_2 = cx.add_model(|cx| Buffer::new(0, "efghi", cx));
4156        let multibuffer = cx.add_model(|cx| {
4157            let mut multibuffer = MultiBuffer::new(0);
4158            multibuffer.push_excerpts(
4159                buffer_1.clone(),
4160                [ExcerptRange {
4161                    context: 0..4,
4162                    primary: None,
4163                }],
4164                cx,
4165            );
4166            multibuffer.push_excerpts(
4167                buffer_2.clone(),
4168                [ExcerptRange {
4169                    context: 0..5,
4170                    primary: None,
4171                }],
4172                cx,
4173            );
4174            multibuffer
4175        });
4176        let old_snapshot = multibuffer.read(cx).snapshot(cx);
4177
4178        assert_eq!(old_snapshot.anchor_before(0).to_offset(&old_snapshot), 0);
4179        assert_eq!(old_snapshot.anchor_after(0).to_offset(&old_snapshot), 0);
4180        assert_eq!(Anchor::min().to_offset(&old_snapshot), 0);
4181        assert_eq!(Anchor::min().to_offset(&old_snapshot), 0);
4182        assert_eq!(Anchor::max().to_offset(&old_snapshot), 10);
4183        assert_eq!(Anchor::max().to_offset(&old_snapshot), 10);
4184
4185        buffer_1.update(cx, |buffer, cx| {
4186            buffer.edit([(0..0, "W")], None, cx);
4187            buffer.edit([(5..5, "X")], None, cx);
4188        });
4189        buffer_2.update(cx, |buffer, cx| {
4190            buffer.edit([(0..0, "Y")], None, cx);
4191            buffer.edit([(6..6, "Z")], None, cx);
4192        });
4193        let new_snapshot = multibuffer.read(cx).snapshot(cx);
4194
4195        assert_eq!(old_snapshot.text(), "abcd\nefghi");
4196        assert_eq!(new_snapshot.text(), "WabcdX\nYefghiZ");
4197
4198        assert_eq!(old_snapshot.anchor_before(0).to_offset(&new_snapshot), 0);
4199        assert_eq!(old_snapshot.anchor_after(0).to_offset(&new_snapshot), 1);
4200        assert_eq!(old_snapshot.anchor_before(1).to_offset(&new_snapshot), 2);
4201        assert_eq!(old_snapshot.anchor_after(1).to_offset(&new_snapshot), 2);
4202        assert_eq!(old_snapshot.anchor_before(2).to_offset(&new_snapshot), 3);
4203        assert_eq!(old_snapshot.anchor_after(2).to_offset(&new_snapshot), 3);
4204        assert_eq!(old_snapshot.anchor_before(5).to_offset(&new_snapshot), 7);
4205        assert_eq!(old_snapshot.anchor_after(5).to_offset(&new_snapshot), 8);
4206        assert_eq!(old_snapshot.anchor_before(10).to_offset(&new_snapshot), 13);
4207        assert_eq!(old_snapshot.anchor_after(10).to_offset(&new_snapshot), 14);
4208    }
4209
4210    #[gpui::test]
4211    fn test_resolving_anchors_after_replacing_their_excerpts(cx: &mut MutableAppContext) {
4212        let buffer_1 = cx.add_model(|cx| Buffer::new(0, "abcd", cx));
4213        let buffer_2 = cx.add_model(|cx| Buffer::new(0, "ABCDEFGHIJKLMNOP", cx));
4214        let multibuffer = cx.add_model(|_| MultiBuffer::new(0));
4215
4216        // Create an insertion id in buffer 1 that doesn't exist in buffer 2.
4217        // Add an excerpt from buffer 1 that spans this new insertion.
4218        buffer_1.update(cx, |buffer, cx| buffer.edit([(4..4, "123")], None, cx));
4219        let excerpt_id_1 = multibuffer.update(cx, |multibuffer, cx| {
4220            multibuffer
4221                .push_excerpts(
4222                    buffer_1.clone(),
4223                    [ExcerptRange {
4224                        context: 0..7,
4225                        primary: None,
4226                    }],
4227                    cx,
4228                )
4229                .pop()
4230                .unwrap()
4231        });
4232
4233        let snapshot_1 = multibuffer.read(cx).snapshot(cx);
4234        assert_eq!(snapshot_1.text(), "abcd123");
4235
4236        // Replace the buffer 1 excerpt with new excerpts from buffer 2.
4237        let (excerpt_id_2, excerpt_id_3) = multibuffer.update(cx, |multibuffer, cx| {
4238            multibuffer.remove_excerpts([excerpt_id_1], cx);
4239            let mut ids = multibuffer
4240                .push_excerpts(
4241                    buffer_2.clone(),
4242                    [
4243                        ExcerptRange {
4244                            context: 0..4,
4245                            primary: None,
4246                        },
4247                        ExcerptRange {
4248                            context: 6..10,
4249                            primary: None,
4250                        },
4251                        ExcerptRange {
4252                            context: 12..16,
4253                            primary: None,
4254                        },
4255                    ],
4256                    cx,
4257                )
4258                .into_iter();
4259            (ids.next().unwrap(), ids.next().unwrap())
4260        });
4261        let snapshot_2 = multibuffer.read(cx).snapshot(cx);
4262        assert_eq!(snapshot_2.text(), "ABCD\nGHIJ\nMNOP");
4263
4264        // The old excerpt id doesn't get reused.
4265        assert_ne!(excerpt_id_2, excerpt_id_1);
4266
4267        // Resolve some anchors from the previous snapshot in the new snapshot.
4268        // The current excerpts are from a different buffer, so we don't attempt to
4269        // resolve the old text anchor in the new buffer.
4270        assert_eq!(
4271            snapshot_2.summary_for_anchor::<usize>(&snapshot_1.anchor_before(2)),
4272            0
4273        );
4274        assert_eq!(
4275            snapshot_2.summaries_for_anchors::<usize, _>(&[
4276                snapshot_1.anchor_before(2),
4277                snapshot_1.anchor_after(3)
4278            ]),
4279            vec![0, 0]
4280        );
4281
4282        // Refresh anchors from the old snapshot. The return value indicates that both
4283        // anchors lost their original excerpt.
4284        let refresh =
4285            snapshot_2.refresh_anchors(&[snapshot_1.anchor_before(2), snapshot_1.anchor_after(3)]);
4286        assert_eq!(
4287            refresh,
4288            &[
4289                (0, snapshot_2.anchor_before(0), false),
4290                (1, snapshot_2.anchor_after(0), false),
4291            ]
4292        );
4293
4294        // Replace the middle excerpt with a smaller excerpt in buffer 2,
4295        // that intersects the old excerpt.
4296        let excerpt_id_5 = multibuffer.update(cx, |multibuffer, cx| {
4297            multibuffer.remove_excerpts([excerpt_id_3], cx);
4298            multibuffer
4299                .insert_excerpts_after(
4300                    excerpt_id_2,
4301                    buffer_2.clone(),
4302                    [ExcerptRange {
4303                        context: 5..8,
4304                        primary: None,
4305                    }],
4306                    cx,
4307                )
4308                .pop()
4309                .unwrap()
4310        });
4311
4312        let snapshot_3 = multibuffer.read(cx).snapshot(cx);
4313        assert_eq!(snapshot_3.text(), "ABCD\nFGH\nMNOP");
4314        assert_ne!(excerpt_id_5, excerpt_id_3);
4315
4316        // Resolve some anchors from the previous snapshot in the new snapshot.
4317        // The third anchor can't be resolved, since its excerpt has been removed,
4318        // so it resolves to the same position as its predecessor.
4319        let anchors = [
4320            snapshot_2.anchor_before(0),
4321            snapshot_2.anchor_after(2),
4322            snapshot_2.anchor_after(6),
4323            snapshot_2.anchor_after(14),
4324        ];
4325        assert_eq!(
4326            snapshot_3.summaries_for_anchors::<usize, _>(&anchors),
4327            &[0, 2, 9, 13]
4328        );
4329
4330        let new_anchors = snapshot_3.refresh_anchors(&anchors);
4331        assert_eq!(
4332            new_anchors.iter().map(|a| (a.0, a.2)).collect::<Vec<_>>(),
4333            &[(0, true), (1, true), (2, true), (3, true)]
4334        );
4335        assert_eq!(
4336            snapshot_3.summaries_for_anchors::<usize, _>(new_anchors.iter().map(|a| &a.1)),
4337            &[0, 2, 7, 13]
4338        );
4339    }
4340
4341    #[gpui::test]
4342    async fn test_diff_hunks_in_range(cx: &mut TestAppContext) {
4343        use git::diff::DiffHunkStatus;
4344
4345        // buffer has two modified hunks with two rows each
4346        let buffer_1 = cx.add_model(|cx| {
4347            let mut buffer = Buffer::new(
4348                0,
4349                "
4350                1.zero
4351                1.ONE
4352                1.TWO
4353                1.three
4354                1.FOUR
4355                1.FIVE
4356                1.six
4357            "
4358                .unindent(),
4359                cx,
4360            );
4361            buffer.set_diff_base(
4362                Some(
4363                    "
4364                1.zero
4365                1.one
4366                1.two
4367                1.three
4368                1.four
4369                1.five
4370                1.six
4371            "
4372                    .unindent(),
4373                ),
4374                cx,
4375            );
4376            buffer
4377        });
4378
4379        // buffer has a deletion hunk and an insertion hunk
4380        let buffer_2 = cx.add_model(|cx| {
4381            let mut buffer = Buffer::new(
4382                0,
4383                "
4384                2.zero
4385                2.one
4386                2.two
4387                2.three
4388                2.four
4389                2.five
4390                2.six
4391            "
4392                .unindent(),
4393                cx,
4394            );
4395            buffer.set_diff_base(
4396                Some(
4397                    "
4398                2.zero
4399                2.one
4400                2.one-and-a-half
4401                2.two
4402                2.three
4403                2.four
4404                2.six
4405            "
4406                    .unindent(),
4407                ),
4408                cx,
4409            );
4410            buffer
4411        });
4412
4413        cx.foreground().run_until_parked();
4414
4415        let multibuffer = cx.add_model(|cx| {
4416            let mut multibuffer = MultiBuffer::new(0);
4417            multibuffer.push_excerpts(
4418                buffer_1.clone(),
4419                [
4420                    // excerpt ends in the middle of a modified hunk
4421                    ExcerptRange {
4422                        context: Point::new(0, 0)..Point::new(1, 5),
4423                        primary: Default::default(),
4424                    },
4425                    // excerpt begins in the middle of a modified hunk
4426                    ExcerptRange {
4427                        context: Point::new(5, 0)..Point::new(6, 5),
4428                        primary: Default::default(),
4429                    },
4430                ],
4431                cx,
4432            );
4433            multibuffer.push_excerpts(
4434                buffer_2.clone(),
4435                [
4436                    // excerpt ends at a deletion
4437                    ExcerptRange {
4438                        context: Point::new(0, 0)..Point::new(1, 5),
4439                        primary: Default::default(),
4440                    },
4441                    // excerpt starts at a deletion
4442                    ExcerptRange {
4443                        context: Point::new(2, 0)..Point::new(2, 5),
4444                        primary: Default::default(),
4445                    },
4446                    // excerpt fully contains a deletion hunk
4447                    ExcerptRange {
4448                        context: Point::new(1, 0)..Point::new(2, 5),
4449                        primary: Default::default(),
4450                    },
4451                    // excerpt fully contains an insertion hunk
4452                    ExcerptRange {
4453                        context: Point::new(4, 0)..Point::new(6, 5),
4454                        primary: Default::default(),
4455                    },
4456                ],
4457                cx,
4458            );
4459            multibuffer
4460        });
4461
4462        let snapshot = multibuffer.read_with(cx, |b, cx| b.snapshot(cx));
4463
4464        assert_eq!(
4465            snapshot.text(),
4466            "
4467                1.zero
4468                1.ONE
4469                1.FIVE
4470                1.six
4471                2.zero
4472                2.one
4473                2.two
4474                2.one
4475                2.two
4476                2.four
4477                2.five
4478                2.six"
4479                .unindent()
4480        );
4481
4482        let expected = [
4483            (DiffHunkStatus::Modified, 1..2),
4484            (DiffHunkStatus::Modified, 2..3),
4485            //TODO: Define better when and where removed hunks show up at range extremities
4486            (DiffHunkStatus::Removed, 6..6),
4487            (DiffHunkStatus::Removed, 8..8),
4488            (DiffHunkStatus::Added, 10..11),
4489        ];
4490
4491        assert_eq!(
4492            snapshot
4493                .git_diff_hunks_in_range(0..12, false)
4494                .map(|hunk| (hunk.status(), hunk.buffer_range))
4495                .collect::<Vec<_>>(),
4496            &expected,
4497        );
4498
4499        assert_eq!(
4500            snapshot
4501                .git_diff_hunks_in_range(0..12, true)
4502                .map(|hunk| (hunk.status(), hunk.buffer_range))
4503                .collect::<Vec<_>>(),
4504            expected
4505                .iter()
4506                .rev()
4507                .cloned()
4508                .collect::<Vec<_>>()
4509                .as_slice(),
4510        );
4511    }
4512
4513    #[gpui::test(iterations = 100)]
4514    fn test_random_multibuffer(cx: &mut MutableAppContext, mut rng: StdRng) {
4515        let operations = env::var("OPERATIONS")
4516            .map(|i| i.parse().expect("invalid `OPERATIONS` variable"))
4517            .unwrap_or(10);
4518
4519        let mut buffers: Vec<ModelHandle<Buffer>> = Vec::new();
4520        let multibuffer = cx.add_model(|_| MultiBuffer::new(0));
4521        let mut excerpt_ids = Vec::<ExcerptId>::new();
4522        let mut expected_excerpts = Vec::<(ModelHandle<Buffer>, Range<text::Anchor>)>::new();
4523        let mut anchors = Vec::new();
4524        let mut old_versions = Vec::new();
4525
4526        for _ in 0..operations {
4527            match rng.gen_range(0..100) {
4528                0..=19 if !buffers.is_empty() => {
4529                    let buffer = buffers.choose(&mut rng).unwrap();
4530                    buffer.update(cx, |buf, cx| buf.randomly_edit(&mut rng, 5, cx));
4531                }
4532                20..=29 if !expected_excerpts.is_empty() => {
4533                    let mut ids_to_remove = vec![];
4534                    for _ in 0..rng.gen_range(1..=3) {
4535                        if expected_excerpts.is_empty() {
4536                            break;
4537                        }
4538
4539                        let ix = rng.gen_range(0..expected_excerpts.len());
4540                        ids_to_remove.push(excerpt_ids.remove(ix));
4541                        let (buffer, range) = expected_excerpts.remove(ix);
4542                        let buffer = buffer.read(cx);
4543                        log::info!(
4544                            "Removing excerpt {}: {:?}",
4545                            ix,
4546                            buffer
4547                                .text_for_range(range.to_offset(buffer))
4548                                .collect::<String>(),
4549                        );
4550                    }
4551                    let snapshot = multibuffer.read(cx).read(cx);
4552                    ids_to_remove.sort_unstable_by(|a, b| a.cmp(&b, &snapshot));
4553                    drop(snapshot);
4554                    multibuffer.update(cx, |multibuffer, cx| {
4555                        multibuffer.remove_excerpts(ids_to_remove, cx)
4556                    });
4557                }
4558                30..=39 if !expected_excerpts.is_empty() => {
4559                    let multibuffer = multibuffer.read(cx).read(cx);
4560                    let offset =
4561                        multibuffer.clip_offset(rng.gen_range(0..=multibuffer.len()), Bias::Left);
4562                    let bias = if rng.gen() { Bias::Left } else { Bias::Right };
4563                    log::info!("Creating anchor at {} with bias {:?}", offset, bias);
4564                    anchors.push(multibuffer.anchor_at(offset, bias));
4565                    anchors.sort_by(|a, b| a.cmp(b, &multibuffer));
4566                }
4567                40..=44 if !anchors.is_empty() => {
4568                    let multibuffer = multibuffer.read(cx).read(cx);
4569                    let prev_len = anchors.len();
4570                    anchors = multibuffer
4571                        .refresh_anchors(&anchors)
4572                        .into_iter()
4573                        .map(|a| a.1)
4574                        .collect();
4575
4576                    // Ensure the newly-refreshed anchors point to a valid excerpt and don't
4577                    // overshoot its boundaries.
4578                    assert_eq!(anchors.len(), prev_len);
4579                    for anchor in &anchors {
4580                        if anchor.excerpt_id == ExcerptId::min()
4581                            || anchor.excerpt_id == ExcerptId::max()
4582                        {
4583                            continue;
4584                        }
4585
4586                        let excerpt = multibuffer.excerpt(anchor.excerpt_id).unwrap();
4587                        assert_eq!(excerpt.id, anchor.excerpt_id);
4588                        assert!(excerpt.contains(anchor));
4589                    }
4590                }
4591                _ => {
4592                    let buffer_handle = if buffers.is_empty() || rng.gen_bool(0.4) {
4593                        let base_text = util::RandomCharIter::new(&mut rng)
4594                            .take(10)
4595                            .collect::<String>();
4596                        buffers.push(cx.add_model(|cx| Buffer::new(0, base_text, cx)));
4597                        buffers.last().unwrap()
4598                    } else {
4599                        buffers.choose(&mut rng).unwrap()
4600                    };
4601
4602                    let buffer = buffer_handle.read(cx);
4603                    let end_ix = buffer.clip_offset(rng.gen_range(0..=buffer.len()), Bias::Right);
4604                    let start_ix = buffer.clip_offset(rng.gen_range(0..=end_ix), Bias::Left);
4605                    let anchor_range = buffer.anchor_before(start_ix)..buffer.anchor_after(end_ix);
4606                    let prev_excerpt_ix = rng.gen_range(0..=expected_excerpts.len());
4607                    let prev_excerpt_id = excerpt_ids
4608                        .get(prev_excerpt_ix)
4609                        .cloned()
4610                        .unwrap_or_else(ExcerptId::max);
4611                    let excerpt_ix = (prev_excerpt_ix + 1).min(expected_excerpts.len());
4612
4613                    log::info!(
4614                        "Inserting excerpt at {} of {} for buffer {}: {:?}[{:?}] = {:?}",
4615                        excerpt_ix,
4616                        expected_excerpts.len(),
4617                        buffer_handle.id(),
4618                        buffer.text(),
4619                        start_ix..end_ix,
4620                        &buffer.text()[start_ix..end_ix]
4621                    );
4622
4623                    let excerpt_id = multibuffer.update(cx, |multibuffer, cx| {
4624                        multibuffer
4625                            .insert_excerpts_after(
4626                                prev_excerpt_id,
4627                                buffer_handle.clone(),
4628                                [ExcerptRange {
4629                                    context: start_ix..end_ix,
4630                                    primary: None,
4631                                }],
4632                                cx,
4633                            )
4634                            .pop()
4635                            .unwrap()
4636                    });
4637
4638                    excerpt_ids.insert(excerpt_ix, excerpt_id);
4639                    expected_excerpts.insert(excerpt_ix, (buffer_handle.clone(), anchor_range));
4640                }
4641            }
4642
4643            if rng.gen_bool(0.3) {
4644                multibuffer.update(cx, |multibuffer, cx| {
4645                    old_versions.push((multibuffer.snapshot(cx), multibuffer.subscribe()));
4646                })
4647            }
4648
4649            let snapshot = multibuffer.read(cx).snapshot(cx);
4650
4651            let mut excerpt_starts = Vec::new();
4652            let mut expected_text = String::new();
4653            let mut expected_buffer_rows = Vec::new();
4654            for (buffer, range) in &expected_excerpts {
4655                let buffer = buffer.read(cx);
4656                let buffer_range = range.to_offset(buffer);
4657
4658                excerpt_starts.push(TextSummary::from(expected_text.as_str()));
4659                expected_text.extend(buffer.text_for_range(buffer_range.clone()));
4660                expected_text.push('\n');
4661
4662                let buffer_row_range = buffer.offset_to_point(buffer_range.start).row
4663                    ..=buffer.offset_to_point(buffer_range.end).row;
4664                for row in buffer_row_range {
4665                    expected_buffer_rows.push(Some(row));
4666                }
4667            }
4668            // Remove final trailing newline.
4669            if !expected_excerpts.is_empty() {
4670                expected_text.pop();
4671            }
4672
4673            // Always report one buffer row
4674            if expected_buffer_rows.is_empty() {
4675                expected_buffer_rows.push(Some(0));
4676            }
4677
4678            assert_eq!(snapshot.text(), expected_text);
4679            log::info!("MultiBuffer text: {:?}", expected_text);
4680
4681            assert_eq!(
4682                snapshot.buffer_rows(0).collect::<Vec<_>>(),
4683                expected_buffer_rows,
4684            );
4685
4686            for _ in 0..5 {
4687                let start_row = rng.gen_range(0..=expected_buffer_rows.len());
4688                assert_eq!(
4689                    snapshot.buffer_rows(start_row as u32).collect::<Vec<_>>(),
4690                    &expected_buffer_rows[start_row..],
4691                    "buffer_rows({})",
4692                    start_row
4693                );
4694            }
4695
4696            assert_eq!(
4697                snapshot.max_buffer_row(),
4698                expected_buffer_rows.into_iter().flatten().max().unwrap()
4699            );
4700
4701            let mut excerpt_starts = excerpt_starts.into_iter();
4702            for (buffer, range) in &expected_excerpts {
4703                let buffer_id = buffer.id();
4704                let buffer = buffer.read(cx);
4705                let buffer_range = range.to_offset(buffer);
4706                let buffer_start_point = buffer.offset_to_point(buffer_range.start);
4707                let buffer_start_point_utf16 =
4708                    buffer.text_summary_for_range::<PointUtf16, _>(0..buffer_range.start);
4709
4710                let excerpt_start = excerpt_starts.next().unwrap();
4711                let mut offset = excerpt_start.len;
4712                let mut buffer_offset = buffer_range.start;
4713                let mut point = excerpt_start.lines;
4714                let mut buffer_point = buffer_start_point;
4715                let mut point_utf16 = excerpt_start.lines_utf16();
4716                let mut buffer_point_utf16 = buffer_start_point_utf16;
4717                for ch in buffer
4718                    .snapshot()
4719                    .chunks(buffer_range.clone(), false)
4720                    .flat_map(|c| c.text.chars())
4721                {
4722                    for _ in 0..ch.len_utf8() {
4723                        let left_offset = snapshot.clip_offset(offset, Bias::Left);
4724                        let right_offset = snapshot.clip_offset(offset, Bias::Right);
4725                        let buffer_left_offset = buffer.clip_offset(buffer_offset, Bias::Left);
4726                        let buffer_right_offset = buffer.clip_offset(buffer_offset, Bias::Right);
4727                        assert_eq!(
4728                            left_offset,
4729                            excerpt_start.len + (buffer_left_offset - buffer_range.start),
4730                            "clip_offset({:?}, Left). buffer: {:?}, buffer offset: {:?}",
4731                            offset,
4732                            buffer_id,
4733                            buffer_offset,
4734                        );
4735                        assert_eq!(
4736                            right_offset,
4737                            excerpt_start.len + (buffer_right_offset - buffer_range.start),
4738                            "clip_offset({:?}, Right). buffer: {:?}, buffer offset: {:?}",
4739                            offset,
4740                            buffer_id,
4741                            buffer_offset,
4742                        );
4743
4744                        let left_point = snapshot.clip_point(point, Bias::Left);
4745                        let right_point = snapshot.clip_point(point, Bias::Right);
4746                        let buffer_left_point = buffer.clip_point(buffer_point, Bias::Left);
4747                        let buffer_right_point = buffer.clip_point(buffer_point, Bias::Right);
4748                        assert_eq!(
4749                            left_point,
4750                            excerpt_start.lines + (buffer_left_point - buffer_start_point),
4751                            "clip_point({:?}, Left). buffer: {:?}, buffer point: {:?}",
4752                            point,
4753                            buffer_id,
4754                            buffer_point,
4755                        );
4756                        assert_eq!(
4757                            right_point,
4758                            excerpt_start.lines + (buffer_right_point - buffer_start_point),
4759                            "clip_point({:?}, Right). buffer: {:?}, buffer point: {:?}",
4760                            point,
4761                            buffer_id,
4762                            buffer_point,
4763                        );
4764
4765                        assert_eq!(
4766                            snapshot.point_to_offset(left_point),
4767                            left_offset,
4768                            "point_to_offset({:?})",
4769                            left_point,
4770                        );
4771                        assert_eq!(
4772                            snapshot.offset_to_point(left_offset),
4773                            left_point,
4774                            "offset_to_point({:?})",
4775                            left_offset,
4776                        );
4777
4778                        offset += 1;
4779                        buffer_offset += 1;
4780                        if ch == '\n' {
4781                            point += Point::new(1, 0);
4782                            buffer_point += Point::new(1, 0);
4783                        } else {
4784                            point += Point::new(0, 1);
4785                            buffer_point += Point::new(0, 1);
4786                        }
4787                    }
4788
4789                    for _ in 0..ch.len_utf16() {
4790                        let left_point_utf16 =
4791                            snapshot.clip_point_utf16(Unclipped(point_utf16), Bias::Left);
4792                        let right_point_utf16 =
4793                            snapshot.clip_point_utf16(Unclipped(point_utf16), Bias::Right);
4794                        let buffer_left_point_utf16 =
4795                            buffer.clip_point_utf16(Unclipped(buffer_point_utf16), Bias::Left);
4796                        let buffer_right_point_utf16 =
4797                            buffer.clip_point_utf16(Unclipped(buffer_point_utf16), Bias::Right);
4798                        assert_eq!(
4799                            left_point_utf16,
4800                            excerpt_start.lines_utf16()
4801                                + (buffer_left_point_utf16 - buffer_start_point_utf16),
4802                            "clip_point_utf16({:?}, Left). buffer: {:?}, buffer point_utf16: {:?}",
4803                            point_utf16,
4804                            buffer_id,
4805                            buffer_point_utf16,
4806                        );
4807                        assert_eq!(
4808                            right_point_utf16,
4809                            excerpt_start.lines_utf16()
4810                                + (buffer_right_point_utf16 - buffer_start_point_utf16),
4811                            "clip_point_utf16({:?}, Right). buffer: {:?}, buffer point_utf16: {:?}",
4812                            point_utf16,
4813                            buffer_id,
4814                            buffer_point_utf16,
4815                        );
4816
4817                        if ch == '\n' {
4818                            point_utf16 += PointUtf16::new(1, 0);
4819                            buffer_point_utf16 += PointUtf16::new(1, 0);
4820                        } else {
4821                            point_utf16 += PointUtf16::new(0, 1);
4822                            buffer_point_utf16 += PointUtf16::new(0, 1);
4823                        }
4824                    }
4825                }
4826            }
4827
4828            for (row, line) in expected_text.split('\n').enumerate() {
4829                assert_eq!(
4830                    snapshot.line_len(row as u32),
4831                    line.len() as u32,
4832                    "line_len({}).",
4833                    row
4834                );
4835            }
4836
4837            let text_rope = Rope::from(expected_text.as_str());
4838            for _ in 0..10 {
4839                let end_ix = text_rope.clip_offset(rng.gen_range(0..=text_rope.len()), Bias::Right);
4840                let start_ix = text_rope.clip_offset(rng.gen_range(0..=end_ix), Bias::Left);
4841
4842                let text_for_range = snapshot
4843                    .text_for_range(start_ix..end_ix)
4844                    .collect::<String>();
4845                assert_eq!(
4846                    text_for_range,
4847                    &expected_text[start_ix..end_ix],
4848                    "incorrect text for range {:?}",
4849                    start_ix..end_ix
4850                );
4851
4852                let excerpted_buffer_ranges = multibuffer
4853                    .read(cx)
4854                    .range_to_buffer_ranges(start_ix..end_ix, cx);
4855                let excerpted_buffers_text = excerpted_buffer_ranges
4856                    .into_iter()
4857                    .map(|(buffer, buffer_range)| {
4858                        buffer
4859                            .read(cx)
4860                            .text_for_range(buffer_range)
4861                            .collect::<String>()
4862                    })
4863                    .collect::<Vec<_>>()
4864                    .join("\n");
4865                assert_eq!(excerpted_buffers_text, text_for_range);
4866
4867                let expected_summary = TextSummary::from(&expected_text[start_ix..end_ix]);
4868                assert_eq!(
4869                    snapshot.text_summary_for_range::<TextSummary, _>(start_ix..end_ix),
4870                    expected_summary,
4871                    "incorrect summary for range {:?}",
4872                    start_ix..end_ix
4873                );
4874            }
4875
4876            // Anchor resolution
4877            let summaries = snapshot.summaries_for_anchors::<usize, _>(&anchors);
4878            assert_eq!(anchors.len(), summaries.len());
4879            for (anchor, resolved_offset) in anchors.iter().zip(summaries) {
4880                assert!(resolved_offset <= snapshot.len());
4881                assert_eq!(
4882                    snapshot.summary_for_anchor::<usize>(anchor),
4883                    resolved_offset
4884                );
4885            }
4886
4887            for _ in 0..10 {
4888                let end_ix = text_rope.clip_offset(rng.gen_range(0..=text_rope.len()), Bias::Right);
4889                assert_eq!(
4890                    snapshot.reversed_chars_at(end_ix).collect::<String>(),
4891                    expected_text[..end_ix].chars().rev().collect::<String>(),
4892                );
4893            }
4894
4895            for _ in 0..10 {
4896                let end_ix = rng.gen_range(0..=text_rope.len());
4897                let start_ix = rng.gen_range(0..=end_ix);
4898                assert_eq!(
4899                    snapshot
4900                        .bytes_in_range(start_ix..end_ix)
4901                        .flatten()
4902                        .copied()
4903                        .collect::<Vec<_>>(),
4904                    expected_text.as_bytes()[start_ix..end_ix].to_vec(),
4905                    "bytes_in_range({:?})",
4906                    start_ix..end_ix,
4907                );
4908            }
4909        }
4910
4911        let snapshot = multibuffer.read(cx).snapshot(cx);
4912        for (old_snapshot, subscription) in old_versions {
4913            let edits = subscription.consume().into_inner();
4914
4915            log::info!(
4916                "applying subscription edits to old text: {:?}: {:?}",
4917                old_snapshot.text(),
4918                edits,
4919            );
4920
4921            let mut text = old_snapshot.text();
4922            for edit in edits {
4923                let new_text: String = snapshot.text_for_range(edit.new.clone()).collect();
4924                text.replace_range(edit.new.start..edit.new.start + edit.old.len(), &new_text);
4925            }
4926            assert_eq!(text.to_string(), snapshot.text());
4927        }
4928    }
4929
4930    #[gpui::test]
4931    fn test_history(cx: &mut MutableAppContext) {
4932        cx.set_global(Settings::test(cx));
4933        let buffer_1 = cx.add_model(|cx| Buffer::new(0, "1234", cx));
4934        let buffer_2 = cx.add_model(|cx| Buffer::new(0, "5678", cx));
4935        let multibuffer = cx.add_model(|_| MultiBuffer::new(0));
4936        let group_interval = multibuffer.read(cx).history.group_interval;
4937        multibuffer.update(cx, |multibuffer, cx| {
4938            multibuffer.push_excerpts(
4939                buffer_1.clone(),
4940                [ExcerptRange {
4941                    context: 0..buffer_1.read(cx).len(),
4942                    primary: None,
4943                }],
4944                cx,
4945            );
4946            multibuffer.push_excerpts(
4947                buffer_2.clone(),
4948                [ExcerptRange {
4949                    context: 0..buffer_2.read(cx).len(),
4950                    primary: None,
4951                }],
4952                cx,
4953            );
4954        });
4955
4956        let mut now = Instant::now();
4957
4958        multibuffer.update(cx, |multibuffer, cx| {
4959            let transaction_1 = multibuffer.start_transaction_at(now, cx).unwrap();
4960            multibuffer.edit(
4961                [
4962                    (Point::new(0, 0)..Point::new(0, 0), "A"),
4963                    (Point::new(1, 0)..Point::new(1, 0), "A"),
4964                ],
4965                None,
4966                cx,
4967            );
4968            multibuffer.edit(
4969                [
4970                    (Point::new(0, 1)..Point::new(0, 1), "B"),
4971                    (Point::new(1, 1)..Point::new(1, 1), "B"),
4972                ],
4973                None,
4974                cx,
4975            );
4976            multibuffer.end_transaction_at(now, cx);
4977            assert_eq!(multibuffer.read(cx).text(), "AB1234\nAB5678");
4978
4979            // Edit buffer 1 through the multibuffer
4980            now += 2 * group_interval;
4981            multibuffer.start_transaction_at(now, cx);
4982            multibuffer.edit([(2..2, "C")], None, cx);
4983            multibuffer.end_transaction_at(now, cx);
4984            assert_eq!(multibuffer.read(cx).text(), "ABC1234\nAB5678");
4985
4986            // Edit buffer 1 independently
4987            buffer_1.update(cx, |buffer_1, cx| {
4988                buffer_1.start_transaction_at(now);
4989                buffer_1.edit([(3..3, "D")], None, cx);
4990                buffer_1.end_transaction_at(now, cx);
4991
4992                now += 2 * group_interval;
4993                buffer_1.start_transaction_at(now);
4994                buffer_1.edit([(4..4, "E")], None, cx);
4995                buffer_1.end_transaction_at(now, cx);
4996            });
4997            assert_eq!(multibuffer.read(cx).text(), "ABCDE1234\nAB5678");
4998
4999            // An undo in the multibuffer undoes the multibuffer transaction
5000            // and also any individual buffer edits that have occured since
5001            // that transaction.
5002            multibuffer.undo(cx);
5003            assert_eq!(multibuffer.read(cx).text(), "AB1234\nAB5678");
5004
5005            multibuffer.undo(cx);
5006            assert_eq!(multibuffer.read(cx).text(), "1234\n5678");
5007
5008            multibuffer.redo(cx);
5009            assert_eq!(multibuffer.read(cx).text(), "AB1234\nAB5678");
5010
5011            multibuffer.redo(cx);
5012            assert_eq!(multibuffer.read(cx).text(), "ABCDE1234\nAB5678");
5013
5014            // Undo buffer 2 independently.
5015            buffer_2.update(cx, |buffer_2, cx| buffer_2.undo(cx));
5016            assert_eq!(multibuffer.read(cx).text(), "ABCDE1234\n5678");
5017
5018            // An undo in the multibuffer undoes the components of the
5019            // the last multibuffer transaction that are not already undone.
5020            multibuffer.undo(cx);
5021            assert_eq!(multibuffer.read(cx).text(), "AB1234\n5678");
5022
5023            multibuffer.undo(cx);
5024            assert_eq!(multibuffer.read(cx).text(), "1234\n5678");
5025
5026            multibuffer.redo(cx);
5027            assert_eq!(multibuffer.read(cx).text(), "AB1234\nAB5678");
5028
5029            buffer_1.update(cx, |buffer_1, cx| buffer_1.redo(cx));
5030            assert_eq!(multibuffer.read(cx).text(), "ABCD1234\nAB5678");
5031
5032            // Redo stack gets cleared after an edit.
5033            now += 2 * group_interval;
5034            multibuffer.start_transaction_at(now, cx);
5035            multibuffer.edit([(0..0, "X")], None, cx);
5036            multibuffer.end_transaction_at(now, cx);
5037            assert_eq!(multibuffer.read(cx).text(), "XABCD1234\nAB5678");
5038            multibuffer.redo(cx);
5039            assert_eq!(multibuffer.read(cx).text(), "XABCD1234\nAB5678");
5040            multibuffer.undo(cx);
5041            assert_eq!(multibuffer.read(cx).text(), "ABCD1234\nAB5678");
5042            multibuffer.undo(cx);
5043            assert_eq!(multibuffer.read(cx).text(), "1234\n5678");
5044
5045            // Transactions can be grouped manually.
5046            multibuffer.redo(cx);
5047            multibuffer.redo(cx);
5048            assert_eq!(multibuffer.read(cx).text(), "XABCD1234\nAB5678");
5049            multibuffer.group_until_transaction(transaction_1, cx);
5050            multibuffer.undo(cx);
5051            assert_eq!(multibuffer.read(cx).text(), "1234\n5678");
5052            multibuffer.redo(cx);
5053            assert_eq!(multibuffer.read(cx).text(), "XABCD1234\nAB5678");
5054        });
5055    }
5056}