multi_buffer.rs

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