multi_buffer.rs

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