multi_buffer.rs

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