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, text, cx));
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, text, cx));
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, text, cx)));
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 = cx.add_model(|cx| Buffer::new(0, sample_text(6, 6, 'a'), cx));
4026        let multibuffer = cx.add_model(|cx| MultiBuffer::singleton(buffer.clone(), cx));
4027
4028        let snapshot = multibuffer.read(cx).snapshot(cx);
4029        assert_eq!(snapshot.text(), buffer.read(cx).text());
4030
4031        assert_eq!(
4032            snapshot.buffer_rows(0).collect::<Vec<_>>(),
4033            (0..buffer.read(cx).row_count())
4034                .map(Some)
4035                .collect::<Vec<_>>()
4036        );
4037
4038        buffer.update(cx, |buffer, cx| buffer.edit([(1..3, "XXX\n")], None, cx));
4039        let snapshot = multibuffer.read(cx).snapshot(cx);
4040
4041        assert_eq!(snapshot.text(), buffer.read(cx).text());
4042        assert_eq!(
4043            snapshot.buffer_rows(0).collect::<Vec<_>>(),
4044            (0..buffer.read(cx).row_count())
4045                .map(Some)
4046                .collect::<Vec<_>>()
4047        );
4048    }
4049
4050    #[gpui::test]
4051    fn test_remote(cx: &mut AppContext) {
4052        let host_buffer = cx.add_model(|cx| Buffer::new(0, "a", cx));
4053        let guest_buffer = cx.add_model(|cx| {
4054            let state = host_buffer.read(cx).to_proto();
4055            let ops = cx
4056                .background()
4057                .block(host_buffer.read(cx).serialize_ops(None, cx));
4058            let mut buffer = Buffer::from_proto(1, state, None).unwrap();
4059            buffer
4060                .apply_ops(
4061                    ops.into_iter()
4062                        .map(|op| language::proto::deserialize_operation(op).unwrap()),
4063                    cx,
4064                )
4065                .unwrap();
4066            buffer
4067        });
4068        let multibuffer = cx.add_model(|cx| MultiBuffer::singleton(guest_buffer.clone(), cx));
4069        let snapshot = multibuffer.read(cx).snapshot(cx);
4070        assert_eq!(snapshot.text(), "a");
4071
4072        guest_buffer.update(cx, |buffer, cx| buffer.edit([(1..1, "b")], None, cx));
4073        let snapshot = multibuffer.read(cx).snapshot(cx);
4074        assert_eq!(snapshot.text(), "ab");
4075
4076        guest_buffer.update(cx, |buffer, cx| buffer.edit([(2..2, "c")], None, cx));
4077        let snapshot = multibuffer.read(cx).snapshot(cx);
4078        assert_eq!(snapshot.text(), "abc");
4079    }
4080
4081    #[gpui::test]
4082    fn test_excerpt_boundaries_and_clipping(cx: &mut AppContext) {
4083        let buffer_1 = cx.add_model(|cx| Buffer::new(0, sample_text(6, 6, 'a'), cx));
4084        let buffer_2 = cx.add_model(|cx| Buffer::new(0, sample_text(6, 6, 'g'), cx));
4085        let multibuffer = cx.add_model(|_| MultiBuffer::new(0));
4086
4087        let events = Rc::new(RefCell::new(Vec::<Event>::new()));
4088        multibuffer.update(cx, |_, cx| {
4089            let events = events.clone();
4090            cx.subscribe(&multibuffer, move |_, _, event, _| {
4091                if let Event::Edited { .. } = event {
4092                    events.borrow_mut().push(event.clone())
4093                }
4094            })
4095            .detach();
4096        });
4097
4098        let subscription = multibuffer.update(cx, |multibuffer, cx| {
4099            let subscription = multibuffer.subscribe();
4100            multibuffer.push_excerpts(
4101                buffer_1.clone(),
4102                [ExcerptRange {
4103                    context: Point::new(1, 2)..Point::new(2, 5),
4104                    primary: None,
4105                }],
4106                cx,
4107            );
4108            assert_eq!(
4109                subscription.consume().into_inner(),
4110                [Edit {
4111                    old: 0..0,
4112                    new: 0..10
4113                }]
4114            );
4115
4116            multibuffer.push_excerpts(
4117                buffer_1.clone(),
4118                [ExcerptRange {
4119                    context: Point::new(3, 3)..Point::new(4, 4),
4120                    primary: None,
4121                }],
4122                cx,
4123            );
4124            multibuffer.push_excerpts(
4125                buffer_2.clone(),
4126                [ExcerptRange {
4127                    context: Point::new(3, 1)..Point::new(3, 3),
4128                    primary: None,
4129                }],
4130                cx,
4131            );
4132            assert_eq!(
4133                subscription.consume().into_inner(),
4134                [Edit {
4135                    old: 10..10,
4136                    new: 10..22
4137                }]
4138            );
4139
4140            subscription
4141        });
4142
4143        // Adding excerpts emits an edited event.
4144        assert_eq!(
4145            events.borrow().as_slice(),
4146            &[
4147                Event::Edited {
4148                    sigleton_buffer_edited: false
4149                },
4150                Event::Edited {
4151                    sigleton_buffer_edited: false
4152                },
4153                Event::Edited {
4154                    sigleton_buffer_edited: false
4155                }
4156            ]
4157        );
4158
4159        let snapshot = multibuffer.read(cx).snapshot(cx);
4160        assert_eq!(
4161            snapshot.text(),
4162            concat!(
4163                "bbbb\n",  // Preserve newlines
4164                "ccccc\n", //
4165                "ddd\n",   //
4166                "eeee\n",  //
4167                "jj"       //
4168            )
4169        );
4170        assert_eq!(
4171            snapshot.buffer_rows(0).collect::<Vec<_>>(),
4172            [Some(1), Some(2), Some(3), Some(4), Some(3)]
4173        );
4174        assert_eq!(
4175            snapshot.buffer_rows(2).collect::<Vec<_>>(),
4176            [Some(3), Some(4), Some(3)]
4177        );
4178        assert_eq!(snapshot.buffer_rows(4).collect::<Vec<_>>(), [Some(3)]);
4179        assert_eq!(snapshot.buffer_rows(5).collect::<Vec<_>>(), []);
4180
4181        assert_eq!(
4182            boundaries_in_range(Point::new(0, 0)..Point::new(4, 2), &snapshot),
4183            &[
4184                (0, "bbbb\nccccc".to_string(), true),
4185                (2, "ddd\neeee".to_string(), false),
4186                (4, "jj".to_string(), true),
4187            ]
4188        );
4189        assert_eq!(
4190            boundaries_in_range(Point::new(0, 0)..Point::new(2, 0), &snapshot),
4191            &[(0, "bbbb\nccccc".to_string(), true)]
4192        );
4193        assert_eq!(
4194            boundaries_in_range(Point::new(1, 0)..Point::new(1, 5), &snapshot),
4195            &[]
4196        );
4197        assert_eq!(
4198            boundaries_in_range(Point::new(1, 0)..Point::new(2, 0), &snapshot),
4199            &[]
4200        );
4201        assert_eq!(
4202            boundaries_in_range(Point::new(1, 0)..Point::new(4, 0), &snapshot),
4203            &[(2, "ddd\neeee".to_string(), false)]
4204        );
4205        assert_eq!(
4206            boundaries_in_range(Point::new(1, 0)..Point::new(4, 0), &snapshot),
4207            &[(2, "ddd\neeee".to_string(), false)]
4208        );
4209        assert_eq!(
4210            boundaries_in_range(Point::new(2, 0)..Point::new(3, 0), &snapshot),
4211            &[(2, "ddd\neeee".to_string(), false)]
4212        );
4213        assert_eq!(
4214            boundaries_in_range(Point::new(4, 0)..Point::new(4, 2), &snapshot),
4215            &[(4, "jj".to_string(), true)]
4216        );
4217        assert_eq!(
4218            boundaries_in_range(Point::new(4, 2)..Point::new(4, 2), &snapshot),
4219            &[]
4220        );
4221
4222        buffer_1.update(cx, |buffer, cx| {
4223            let text = "\n";
4224            buffer.edit(
4225                [
4226                    (Point::new(0, 0)..Point::new(0, 0), text),
4227                    (Point::new(2, 1)..Point::new(2, 3), text),
4228                ],
4229                None,
4230                cx,
4231            );
4232        });
4233
4234        let snapshot = multibuffer.read(cx).snapshot(cx);
4235        assert_eq!(
4236            snapshot.text(),
4237            concat!(
4238                "bbbb\n", // Preserve newlines
4239                "c\n",    //
4240                "cc\n",   //
4241                "ddd\n",  //
4242                "eeee\n", //
4243                "jj"      //
4244            )
4245        );
4246
4247        assert_eq!(
4248            subscription.consume().into_inner(),
4249            [Edit {
4250                old: 6..8,
4251                new: 6..7
4252            }]
4253        );
4254
4255        let snapshot = multibuffer.read(cx).snapshot(cx);
4256        assert_eq!(
4257            snapshot.clip_point(Point::new(0, 5), Bias::Left),
4258            Point::new(0, 4)
4259        );
4260        assert_eq!(
4261            snapshot.clip_point(Point::new(0, 5), Bias::Right),
4262            Point::new(0, 4)
4263        );
4264        assert_eq!(
4265            snapshot.clip_point(Point::new(5, 1), Bias::Right),
4266            Point::new(5, 1)
4267        );
4268        assert_eq!(
4269            snapshot.clip_point(Point::new(5, 2), Bias::Right),
4270            Point::new(5, 2)
4271        );
4272        assert_eq!(
4273            snapshot.clip_point(Point::new(5, 3), Bias::Right),
4274            Point::new(5, 2)
4275        );
4276
4277        let snapshot = multibuffer.update(cx, |multibuffer, cx| {
4278            let (buffer_2_excerpt_id, _) =
4279                multibuffer.excerpts_for_buffer(&buffer_2, cx)[0].clone();
4280            multibuffer.remove_excerpts([buffer_2_excerpt_id], cx);
4281            multibuffer.snapshot(cx)
4282        });
4283
4284        assert_eq!(
4285            snapshot.text(),
4286            concat!(
4287                "bbbb\n", // Preserve newlines
4288                "c\n",    //
4289                "cc\n",   //
4290                "ddd\n",  //
4291                "eeee",   //
4292            )
4293        );
4294
4295        fn boundaries_in_range(
4296            range: Range<Point>,
4297            snapshot: &MultiBufferSnapshot,
4298        ) -> Vec<(u32, String, bool)> {
4299            snapshot
4300                .excerpt_boundaries_in_range(range)
4301                .map(|boundary| {
4302                    (
4303                        boundary.row,
4304                        boundary
4305                            .buffer
4306                            .text_for_range(boundary.range.context)
4307                            .collect::<String>(),
4308                        boundary.starts_new_buffer,
4309                    )
4310                })
4311                .collect::<Vec<_>>()
4312        }
4313    }
4314
4315    #[gpui::test]
4316    fn test_excerpt_events(cx: &mut AppContext) {
4317        let buffer_1 = cx.add_model(|cx| Buffer::new(0, sample_text(10, 3, 'a'), cx));
4318        let buffer_2 = cx.add_model(|cx| Buffer::new(0, sample_text(10, 3, 'm'), cx));
4319
4320        let leader_multibuffer = cx.add_model(|_| MultiBuffer::new(0));
4321        let follower_multibuffer = cx.add_model(|_| MultiBuffer::new(0));
4322        let follower_edit_event_count = Rc::new(RefCell::new(0));
4323
4324        follower_multibuffer.update(cx, |_, cx| {
4325            let follower_edit_event_count = follower_edit_event_count.clone();
4326            cx.subscribe(
4327                &leader_multibuffer,
4328                move |follower, _, event, cx| match event.clone() {
4329                    Event::ExcerptsAdded {
4330                        buffer,
4331                        predecessor,
4332                        excerpts,
4333                    } => follower.insert_excerpts_with_ids_after(predecessor, buffer, excerpts, cx),
4334                    Event::ExcerptsRemoved { ids } => follower.remove_excerpts(ids, cx),
4335                    Event::Edited { .. } => {
4336                        *follower_edit_event_count.borrow_mut() += 1;
4337                    }
4338                    _ => {}
4339                },
4340            )
4341            .detach();
4342        });
4343
4344        leader_multibuffer.update(cx, |leader, cx| {
4345            leader.push_excerpts(
4346                buffer_1.clone(),
4347                [
4348                    ExcerptRange {
4349                        context: 0..8,
4350                        primary: None,
4351                    },
4352                    ExcerptRange {
4353                        context: 12..16,
4354                        primary: None,
4355                    },
4356                ],
4357                cx,
4358            );
4359            leader.insert_excerpts_after(
4360                leader.excerpt_ids()[0],
4361                buffer_2.clone(),
4362                [
4363                    ExcerptRange {
4364                        context: 0..5,
4365                        primary: None,
4366                    },
4367                    ExcerptRange {
4368                        context: 10..15,
4369                        primary: None,
4370                    },
4371                ],
4372                cx,
4373            )
4374        });
4375        assert_eq!(
4376            leader_multibuffer.read(cx).snapshot(cx).text(),
4377            follower_multibuffer.read(cx).snapshot(cx).text(),
4378        );
4379        assert_eq!(*follower_edit_event_count.borrow(), 2);
4380
4381        leader_multibuffer.update(cx, |leader, cx| {
4382            let excerpt_ids = leader.excerpt_ids();
4383            leader.remove_excerpts([excerpt_ids[1], excerpt_ids[3]], cx);
4384        });
4385        assert_eq!(
4386            leader_multibuffer.read(cx).snapshot(cx).text(),
4387            follower_multibuffer.read(cx).snapshot(cx).text(),
4388        );
4389        assert_eq!(*follower_edit_event_count.borrow(), 3);
4390
4391        // Removing an empty set of excerpts is a noop.
4392        leader_multibuffer.update(cx, |leader, cx| {
4393            leader.remove_excerpts([], cx);
4394        });
4395        assert_eq!(
4396            leader_multibuffer.read(cx).snapshot(cx).text(),
4397            follower_multibuffer.read(cx).snapshot(cx).text(),
4398        );
4399        assert_eq!(*follower_edit_event_count.borrow(), 3);
4400
4401        // Adding an empty set of excerpts is a noop.
4402        leader_multibuffer.update(cx, |leader, cx| {
4403            leader.push_excerpts::<usize>(buffer_2.clone(), [], cx);
4404        });
4405        assert_eq!(
4406            leader_multibuffer.read(cx).snapshot(cx).text(),
4407            follower_multibuffer.read(cx).snapshot(cx).text(),
4408        );
4409        assert_eq!(*follower_edit_event_count.borrow(), 3);
4410
4411        leader_multibuffer.update(cx, |leader, cx| {
4412            leader.clear(cx);
4413        });
4414        assert_eq!(
4415            leader_multibuffer.read(cx).snapshot(cx).text(),
4416            follower_multibuffer.read(cx).snapshot(cx).text(),
4417        );
4418        assert_eq!(*follower_edit_event_count.borrow(), 4);
4419    }
4420
4421    #[gpui::test]
4422    fn test_push_excerpts_with_context_lines(cx: &mut AppContext) {
4423        let buffer = cx.add_model(|cx| Buffer::new(0, sample_text(20, 3, 'a'), cx));
4424        let multibuffer = cx.add_model(|_| MultiBuffer::new(0));
4425        let anchor_ranges = multibuffer.update(cx, |multibuffer, cx| {
4426            multibuffer.push_excerpts_with_context_lines(
4427                buffer.clone(),
4428                vec![
4429                    Point::new(3, 2)..Point::new(4, 2),
4430                    Point::new(7, 1)..Point::new(7, 3),
4431                    Point::new(15, 0)..Point::new(15, 0),
4432                ],
4433                2,
4434                cx,
4435            )
4436        });
4437
4438        let snapshot = multibuffer.read(cx).snapshot(cx);
4439        assert_eq!(
4440            snapshot.text(),
4441            "bbb\nccc\nddd\neee\nfff\nggg\nhhh\niii\njjj\n\nnnn\nooo\nppp\nqqq\nrrr\n"
4442        );
4443
4444        assert_eq!(
4445            anchor_ranges
4446                .iter()
4447                .map(|range| range.to_point(&snapshot))
4448                .collect::<Vec<_>>(),
4449            vec![
4450                Point::new(2, 2)..Point::new(3, 2),
4451                Point::new(6, 1)..Point::new(6, 3),
4452                Point::new(12, 0)..Point::new(12, 0)
4453            ]
4454        );
4455    }
4456
4457    #[gpui::test]
4458    async fn test_stream_excerpts_with_context_lines(cx: &mut TestAppContext) {
4459        let buffer = cx.add_model(|cx| Buffer::new(0, sample_text(20, 3, 'a'), cx));
4460        let multibuffer = cx.add_model(|_| MultiBuffer::new(0));
4461        let anchor_ranges = multibuffer.update(cx, |multibuffer, cx| {
4462            let snapshot = buffer.read(cx);
4463            let ranges = vec![
4464                snapshot.anchor_before(Point::new(3, 2))..snapshot.anchor_before(Point::new(4, 2)),
4465                snapshot.anchor_before(Point::new(7, 1))..snapshot.anchor_before(Point::new(7, 3)),
4466                snapshot.anchor_before(Point::new(15, 0))
4467                    ..snapshot.anchor_before(Point::new(15, 0)),
4468            ];
4469            multibuffer.stream_excerpts_with_context_lines(buffer.clone(), ranges, 2, cx)
4470        });
4471
4472        let anchor_ranges = anchor_ranges.collect::<Vec<_>>().await;
4473
4474        let snapshot = multibuffer.read_with(cx, |multibuffer, cx| multibuffer.snapshot(cx));
4475        assert_eq!(
4476            snapshot.text(),
4477            "bbb\nccc\nddd\neee\nfff\nggg\nhhh\niii\njjj\n\nnnn\nooo\nppp\nqqq\nrrr\n"
4478        );
4479
4480        assert_eq!(
4481            anchor_ranges
4482                .iter()
4483                .map(|range| range.to_point(&snapshot))
4484                .collect::<Vec<_>>(),
4485            vec![
4486                Point::new(2, 2)..Point::new(3, 2),
4487                Point::new(6, 1)..Point::new(6, 3),
4488                Point::new(12, 0)..Point::new(12, 0)
4489            ]
4490        );
4491    }
4492
4493    #[gpui::test]
4494    fn test_empty_multibuffer(cx: &mut AppContext) {
4495        let multibuffer = cx.add_model(|_| MultiBuffer::new(0));
4496
4497        let snapshot = multibuffer.read(cx).snapshot(cx);
4498        assert_eq!(snapshot.text(), "");
4499        assert_eq!(snapshot.buffer_rows(0).collect::<Vec<_>>(), &[Some(0)]);
4500        assert_eq!(snapshot.buffer_rows(1).collect::<Vec<_>>(), &[]);
4501    }
4502
4503    #[gpui::test]
4504    fn test_singleton_multibuffer_anchors(cx: &mut AppContext) {
4505        let buffer = cx.add_model(|cx| Buffer::new(0, "abcd", cx));
4506        let multibuffer = cx.add_model(|cx| MultiBuffer::singleton(buffer.clone(), cx));
4507        let old_snapshot = multibuffer.read(cx).snapshot(cx);
4508        buffer.update(cx, |buffer, cx| {
4509            buffer.edit([(0..0, "X")], None, cx);
4510            buffer.edit([(5..5, "Y")], None, cx);
4511        });
4512        let new_snapshot = multibuffer.read(cx).snapshot(cx);
4513
4514        assert_eq!(old_snapshot.text(), "abcd");
4515        assert_eq!(new_snapshot.text(), "XabcdY");
4516
4517        assert_eq!(old_snapshot.anchor_before(0).to_offset(&new_snapshot), 0);
4518        assert_eq!(old_snapshot.anchor_after(0).to_offset(&new_snapshot), 1);
4519        assert_eq!(old_snapshot.anchor_before(4).to_offset(&new_snapshot), 5);
4520        assert_eq!(old_snapshot.anchor_after(4).to_offset(&new_snapshot), 6);
4521    }
4522
4523    #[gpui::test]
4524    fn test_multibuffer_anchors(cx: &mut AppContext) {
4525        let buffer_1 = cx.add_model(|cx| Buffer::new(0, "abcd", cx));
4526        let buffer_2 = cx.add_model(|cx| Buffer::new(0, "efghi", cx));
4527        let multibuffer = cx.add_model(|cx| {
4528            let mut multibuffer = MultiBuffer::new(0);
4529            multibuffer.push_excerpts(
4530                buffer_1.clone(),
4531                [ExcerptRange {
4532                    context: 0..4,
4533                    primary: None,
4534                }],
4535                cx,
4536            );
4537            multibuffer.push_excerpts(
4538                buffer_2.clone(),
4539                [ExcerptRange {
4540                    context: 0..5,
4541                    primary: None,
4542                }],
4543                cx,
4544            );
4545            multibuffer
4546        });
4547        let old_snapshot = multibuffer.read(cx).snapshot(cx);
4548
4549        assert_eq!(old_snapshot.anchor_before(0).to_offset(&old_snapshot), 0);
4550        assert_eq!(old_snapshot.anchor_after(0).to_offset(&old_snapshot), 0);
4551        assert_eq!(Anchor::min().to_offset(&old_snapshot), 0);
4552        assert_eq!(Anchor::min().to_offset(&old_snapshot), 0);
4553        assert_eq!(Anchor::max().to_offset(&old_snapshot), 10);
4554        assert_eq!(Anchor::max().to_offset(&old_snapshot), 10);
4555
4556        buffer_1.update(cx, |buffer, cx| {
4557            buffer.edit([(0..0, "W")], None, cx);
4558            buffer.edit([(5..5, "X")], None, cx);
4559        });
4560        buffer_2.update(cx, |buffer, cx| {
4561            buffer.edit([(0..0, "Y")], None, cx);
4562            buffer.edit([(6..6, "Z")], None, cx);
4563        });
4564        let new_snapshot = multibuffer.read(cx).snapshot(cx);
4565
4566        assert_eq!(old_snapshot.text(), "abcd\nefghi");
4567        assert_eq!(new_snapshot.text(), "WabcdX\nYefghiZ");
4568
4569        assert_eq!(old_snapshot.anchor_before(0).to_offset(&new_snapshot), 0);
4570        assert_eq!(old_snapshot.anchor_after(0).to_offset(&new_snapshot), 1);
4571        assert_eq!(old_snapshot.anchor_before(1).to_offset(&new_snapshot), 2);
4572        assert_eq!(old_snapshot.anchor_after(1).to_offset(&new_snapshot), 2);
4573        assert_eq!(old_snapshot.anchor_before(2).to_offset(&new_snapshot), 3);
4574        assert_eq!(old_snapshot.anchor_after(2).to_offset(&new_snapshot), 3);
4575        assert_eq!(old_snapshot.anchor_before(5).to_offset(&new_snapshot), 7);
4576        assert_eq!(old_snapshot.anchor_after(5).to_offset(&new_snapshot), 8);
4577        assert_eq!(old_snapshot.anchor_before(10).to_offset(&new_snapshot), 13);
4578        assert_eq!(old_snapshot.anchor_after(10).to_offset(&new_snapshot), 14);
4579    }
4580
4581    #[gpui::test]
4582    fn test_resolving_anchors_after_replacing_their_excerpts(cx: &mut AppContext) {
4583        let buffer_1 = cx.add_model(|cx| Buffer::new(0, "abcd", cx));
4584        let buffer_2 = cx.add_model(|cx| Buffer::new(0, "ABCDEFGHIJKLMNOP", cx));
4585        let multibuffer = cx.add_model(|_| MultiBuffer::new(0));
4586
4587        // Create an insertion id in buffer 1 that doesn't exist in buffer 2.
4588        // Add an excerpt from buffer 1 that spans this new insertion.
4589        buffer_1.update(cx, |buffer, cx| buffer.edit([(4..4, "123")], None, cx));
4590        let excerpt_id_1 = multibuffer.update(cx, |multibuffer, cx| {
4591            multibuffer
4592                .push_excerpts(
4593                    buffer_1.clone(),
4594                    [ExcerptRange {
4595                        context: 0..7,
4596                        primary: None,
4597                    }],
4598                    cx,
4599                )
4600                .pop()
4601                .unwrap()
4602        });
4603
4604        let snapshot_1 = multibuffer.read(cx).snapshot(cx);
4605        assert_eq!(snapshot_1.text(), "abcd123");
4606
4607        // Replace the buffer 1 excerpt with new excerpts from buffer 2.
4608        let (excerpt_id_2, excerpt_id_3) = multibuffer.update(cx, |multibuffer, cx| {
4609            multibuffer.remove_excerpts([excerpt_id_1], cx);
4610            let mut ids = multibuffer
4611                .push_excerpts(
4612                    buffer_2.clone(),
4613                    [
4614                        ExcerptRange {
4615                            context: 0..4,
4616                            primary: None,
4617                        },
4618                        ExcerptRange {
4619                            context: 6..10,
4620                            primary: None,
4621                        },
4622                        ExcerptRange {
4623                            context: 12..16,
4624                            primary: None,
4625                        },
4626                    ],
4627                    cx,
4628                )
4629                .into_iter();
4630            (ids.next().unwrap(), ids.next().unwrap())
4631        });
4632        let snapshot_2 = multibuffer.read(cx).snapshot(cx);
4633        assert_eq!(snapshot_2.text(), "ABCD\nGHIJ\nMNOP");
4634
4635        // The old excerpt id doesn't get reused.
4636        assert_ne!(excerpt_id_2, excerpt_id_1);
4637
4638        // Resolve some anchors from the previous snapshot in the new snapshot.
4639        // The current excerpts are from a different buffer, so we don't attempt to
4640        // resolve the old text anchor in the new buffer.
4641        assert_eq!(
4642            snapshot_2.summary_for_anchor::<usize>(&snapshot_1.anchor_before(2)),
4643            0
4644        );
4645        assert_eq!(
4646            snapshot_2.summaries_for_anchors::<usize, _>(&[
4647                snapshot_1.anchor_before(2),
4648                snapshot_1.anchor_after(3)
4649            ]),
4650            vec![0, 0]
4651        );
4652
4653        // Refresh anchors from the old snapshot. The return value indicates that both
4654        // anchors lost their original excerpt.
4655        let refresh =
4656            snapshot_2.refresh_anchors(&[snapshot_1.anchor_before(2), snapshot_1.anchor_after(3)]);
4657        assert_eq!(
4658            refresh,
4659            &[
4660                (0, snapshot_2.anchor_before(0), false),
4661                (1, snapshot_2.anchor_after(0), false),
4662            ]
4663        );
4664
4665        // Replace the middle excerpt with a smaller excerpt in buffer 2,
4666        // that intersects the old excerpt.
4667        let excerpt_id_5 = multibuffer.update(cx, |multibuffer, cx| {
4668            multibuffer.remove_excerpts([excerpt_id_3], cx);
4669            multibuffer
4670                .insert_excerpts_after(
4671                    excerpt_id_2,
4672                    buffer_2.clone(),
4673                    [ExcerptRange {
4674                        context: 5..8,
4675                        primary: None,
4676                    }],
4677                    cx,
4678                )
4679                .pop()
4680                .unwrap()
4681        });
4682
4683        let snapshot_3 = multibuffer.read(cx).snapshot(cx);
4684        assert_eq!(snapshot_3.text(), "ABCD\nFGH\nMNOP");
4685        assert_ne!(excerpt_id_5, excerpt_id_3);
4686
4687        // Resolve some anchors from the previous snapshot in the new snapshot.
4688        // The third anchor can't be resolved, since its excerpt has been removed,
4689        // so it resolves to the same position as its predecessor.
4690        let anchors = [
4691            snapshot_2.anchor_before(0),
4692            snapshot_2.anchor_after(2),
4693            snapshot_2.anchor_after(6),
4694            snapshot_2.anchor_after(14),
4695        ];
4696        assert_eq!(
4697            snapshot_3.summaries_for_anchors::<usize, _>(&anchors),
4698            &[0, 2, 9, 13]
4699        );
4700
4701        let new_anchors = snapshot_3.refresh_anchors(&anchors);
4702        assert_eq!(
4703            new_anchors.iter().map(|a| (a.0, a.2)).collect::<Vec<_>>(),
4704            &[(0, true), (1, true), (2, true), (3, true)]
4705        );
4706        assert_eq!(
4707            snapshot_3.summaries_for_anchors::<usize, _>(new_anchors.iter().map(|a| &a.1)),
4708            &[0, 2, 7, 13]
4709        );
4710    }
4711
4712    #[gpui::test]
4713    async fn test_diff_hunks_in_range(cx: &mut TestAppContext) {
4714        use git::diff::DiffHunkStatus;
4715        init_test(cx, |_| {});
4716
4717        let fs = FakeFs::new(cx.background());
4718        let project = Project::test(fs, [], cx).await;
4719
4720        // buffer has two modified hunks with two rows each
4721        let buffer_1 = project
4722            .update(cx, |project, cx| {
4723                project.create_buffer(
4724                    "
4725                        1.zero
4726                        1.ONE
4727                        1.TWO
4728                        1.three
4729                        1.FOUR
4730                        1.FIVE
4731                        1.six
4732                    "
4733                    .unindent()
4734                    .as_str(),
4735                    None,
4736                    cx,
4737                )
4738            })
4739            .unwrap();
4740        buffer_1.update(cx, |buffer, cx| {
4741            buffer.set_diff_base(
4742                Some(
4743                    "
4744                        1.zero
4745                        1.one
4746                        1.two
4747                        1.three
4748                        1.four
4749                        1.five
4750                        1.six
4751                    "
4752                    .unindent(),
4753                ),
4754                cx,
4755            );
4756        });
4757
4758        // buffer has a deletion hunk and an insertion hunk
4759        let buffer_2 = project
4760            .update(cx, |project, cx| {
4761                project.create_buffer(
4762                    "
4763                        2.zero
4764                        2.one
4765                        2.two
4766                        2.three
4767                        2.four
4768                        2.five
4769                        2.six
4770                    "
4771                    .unindent()
4772                    .as_str(),
4773                    None,
4774                    cx,
4775                )
4776            })
4777            .unwrap();
4778        buffer_2.update(cx, |buffer, cx| {
4779            buffer.set_diff_base(
4780                Some(
4781                    "
4782                        2.zero
4783                        2.one
4784                        2.one-and-a-half
4785                        2.two
4786                        2.three
4787                        2.four
4788                        2.six
4789                    "
4790                    .unindent(),
4791                ),
4792                cx,
4793            );
4794        });
4795
4796        cx.foreground().run_until_parked();
4797
4798        let multibuffer = cx.add_model(|cx| {
4799            let mut multibuffer = MultiBuffer::new(0);
4800            multibuffer.push_excerpts(
4801                buffer_1.clone(),
4802                [
4803                    // excerpt ends in the middle of a modified hunk
4804                    ExcerptRange {
4805                        context: Point::new(0, 0)..Point::new(1, 5),
4806                        primary: Default::default(),
4807                    },
4808                    // excerpt begins in the middle of a modified hunk
4809                    ExcerptRange {
4810                        context: Point::new(5, 0)..Point::new(6, 5),
4811                        primary: Default::default(),
4812                    },
4813                ],
4814                cx,
4815            );
4816            multibuffer.push_excerpts(
4817                buffer_2.clone(),
4818                [
4819                    // excerpt ends at a deletion
4820                    ExcerptRange {
4821                        context: Point::new(0, 0)..Point::new(1, 5),
4822                        primary: Default::default(),
4823                    },
4824                    // excerpt starts at a deletion
4825                    ExcerptRange {
4826                        context: Point::new(2, 0)..Point::new(2, 5),
4827                        primary: Default::default(),
4828                    },
4829                    // excerpt fully contains a deletion hunk
4830                    ExcerptRange {
4831                        context: Point::new(1, 0)..Point::new(2, 5),
4832                        primary: Default::default(),
4833                    },
4834                    // excerpt fully contains an insertion hunk
4835                    ExcerptRange {
4836                        context: Point::new(4, 0)..Point::new(6, 5),
4837                        primary: Default::default(),
4838                    },
4839                ],
4840                cx,
4841            );
4842            multibuffer
4843        });
4844
4845        let snapshot = multibuffer.read_with(cx, |b, cx| b.snapshot(cx));
4846
4847        assert_eq!(
4848            snapshot.text(),
4849            "
4850                1.zero
4851                1.ONE
4852                1.FIVE
4853                1.six
4854                2.zero
4855                2.one
4856                2.two
4857                2.one
4858                2.two
4859                2.four
4860                2.five
4861                2.six"
4862                .unindent()
4863        );
4864
4865        let expected = [
4866            (DiffHunkStatus::Modified, 1..2),
4867            (DiffHunkStatus::Modified, 2..3),
4868            //TODO: Define better when and where removed hunks show up at range extremities
4869            (DiffHunkStatus::Removed, 6..6),
4870            (DiffHunkStatus::Removed, 8..8),
4871            (DiffHunkStatus::Added, 10..11),
4872        ];
4873
4874        assert_eq!(
4875            snapshot
4876                .git_diff_hunks_in_range(0..12)
4877                .map(|hunk| (hunk.status(), hunk.buffer_range))
4878                .collect::<Vec<_>>(),
4879            &expected,
4880        );
4881
4882        assert_eq!(
4883            snapshot
4884                .git_diff_hunks_in_range_rev(0..12)
4885                .map(|hunk| (hunk.status(), hunk.buffer_range))
4886                .collect::<Vec<_>>(),
4887            expected
4888                .iter()
4889                .rev()
4890                .cloned()
4891                .collect::<Vec<_>>()
4892                .as_slice(),
4893        );
4894    }
4895
4896    #[gpui::test(iterations = 100)]
4897    fn test_random_multibuffer(cx: &mut AppContext, mut rng: StdRng) {
4898        let operations = env::var("OPERATIONS")
4899            .map(|i| i.parse().expect("invalid `OPERATIONS` variable"))
4900            .unwrap_or(10);
4901
4902        let mut buffers: Vec<ModelHandle<Buffer>> = Vec::new();
4903        let multibuffer = cx.add_model(|_| MultiBuffer::new(0));
4904        let mut excerpt_ids = Vec::<ExcerptId>::new();
4905        let mut expected_excerpts = Vec::<(ModelHandle<Buffer>, Range<text::Anchor>)>::new();
4906        let mut anchors = Vec::new();
4907        let mut old_versions = Vec::new();
4908
4909        for _ in 0..operations {
4910            match rng.gen_range(0..100) {
4911                0..=19 if !buffers.is_empty() => {
4912                    let buffer = buffers.choose(&mut rng).unwrap();
4913                    buffer.update(cx, |buf, cx| buf.randomly_edit(&mut rng, 5, cx));
4914                }
4915                20..=29 if !expected_excerpts.is_empty() => {
4916                    let mut ids_to_remove = vec![];
4917                    for _ in 0..rng.gen_range(1..=3) {
4918                        if expected_excerpts.is_empty() {
4919                            break;
4920                        }
4921
4922                        let ix = rng.gen_range(0..expected_excerpts.len());
4923                        ids_to_remove.push(excerpt_ids.remove(ix));
4924                        let (buffer, range) = expected_excerpts.remove(ix);
4925                        let buffer = buffer.read(cx);
4926                        log::info!(
4927                            "Removing excerpt {}: {:?}",
4928                            ix,
4929                            buffer
4930                                .text_for_range(range.to_offset(buffer))
4931                                .collect::<String>(),
4932                        );
4933                    }
4934                    let snapshot = multibuffer.read(cx).read(cx);
4935                    ids_to_remove.sort_unstable_by(|a, b| a.cmp(&b, &snapshot));
4936                    drop(snapshot);
4937                    multibuffer.update(cx, |multibuffer, cx| {
4938                        multibuffer.remove_excerpts(ids_to_remove, cx)
4939                    });
4940                }
4941                30..=39 if !expected_excerpts.is_empty() => {
4942                    let multibuffer = multibuffer.read(cx).read(cx);
4943                    let offset =
4944                        multibuffer.clip_offset(rng.gen_range(0..=multibuffer.len()), Bias::Left);
4945                    let bias = if rng.gen() { Bias::Left } else { Bias::Right };
4946                    log::info!("Creating anchor at {} with bias {:?}", offset, bias);
4947                    anchors.push(multibuffer.anchor_at(offset, bias));
4948                    anchors.sort_by(|a, b| a.cmp(b, &multibuffer));
4949                }
4950                40..=44 if !anchors.is_empty() => {
4951                    let multibuffer = multibuffer.read(cx).read(cx);
4952                    let prev_len = anchors.len();
4953                    anchors = multibuffer
4954                        .refresh_anchors(&anchors)
4955                        .into_iter()
4956                        .map(|a| a.1)
4957                        .collect();
4958
4959                    // Ensure the newly-refreshed anchors point to a valid excerpt and don't
4960                    // overshoot its boundaries.
4961                    assert_eq!(anchors.len(), prev_len);
4962                    for anchor in &anchors {
4963                        if anchor.excerpt_id == ExcerptId::min()
4964                            || anchor.excerpt_id == ExcerptId::max()
4965                        {
4966                            continue;
4967                        }
4968
4969                        let excerpt = multibuffer.excerpt(anchor.excerpt_id).unwrap();
4970                        assert_eq!(excerpt.id, anchor.excerpt_id);
4971                        assert!(excerpt.contains(anchor));
4972                    }
4973                }
4974                _ => {
4975                    let buffer_handle = if buffers.is_empty() || rng.gen_bool(0.4) {
4976                        let base_text = util::RandomCharIter::new(&mut rng)
4977                            .take(10)
4978                            .collect::<String>();
4979                        buffers.push(cx.add_model(|cx| Buffer::new(0, base_text, cx)));
4980                        buffers.last().unwrap()
4981                    } else {
4982                        buffers.choose(&mut rng).unwrap()
4983                    };
4984
4985                    let buffer = buffer_handle.read(cx);
4986                    let end_ix = buffer.clip_offset(rng.gen_range(0..=buffer.len()), Bias::Right);
4987                    let start_ix = buffer.clip_offset(rng.gen_range(0..=end_ix), Bias::Left);
4988                    let anchor_range = buffer.anchor_before(start_ix)..buffer.anchor_after(end_ix);
4989                    let prev_excerpt_ix = rng.gen_range(0..=expected_excerpts.len());
4990                    let prev_excerpt_id = excerpt_ids
4991                        .get(prev_excerpt_ix)
4992                        .cloned()
4993                        .unwrap_or_else(ExcerptId::max);
4994                    let excerpt_ix = (prev_excerpt_ix + 1).min(expected_excerpts.len());
4995
4996                    log::info!(
4997                        "Inserting excerpt at {} of {} for buffer {}: {:?}[{:?}] = {:?}",
4998                        excerpt_ix,
4999                        expected_excerpts.len(),
5000                        buffer_handle.read(cx).remote_id(),
5001                        buffer.text(),
5002                        start_ix..end_ix,
5003                        &buffer.text()[start_ix..end_ix]
5004                    );
5005
5006                    let excerpt_id = multibuffer.update(cx, |multibuffer, cx| {
5007                        multibuffer
5008                            .insert_excerpts_after(
5009                                prev_excerpt_id,
5010                                buffer_handle.clone(),
5011                                [ExcerptRange {
5012                                    context: start_ix..end_ix,
5013                                    primary: None,
5014                                }],
5015                                cx,
5016                            )
5017                            .pop()
5018                            .unwrap()
5019                    });
5020
5021                    excerpt_ids.insert(excerpt_ix, excerpt_id);
5022                    expected_excerpts.insert(excerpt_ix, (buffer_handle.clone(), anchor_range));
5023                }
5024            }
5025
5026            if rng.gen_bool(0.3) {
5027                multibuffer.update(cx, |multibuffer, cx| {
5028                    old_versions.push((multibuffer.snapshot(cx), multibuffer.subscribe()));
5029                })
5030            }
5031
5032            let snapshot = multibuffer.read(cx).snapshot(cx);
5033
5034            let mut excerpt_starts = Vec::new();
5035            let mut expected_text = String::new();
5036            let mut expected_buffer_rows = Vec::new();
5037            for (buffer, range) in &expected_excerpts {
5038                let buffer = buffer.read(cx);
5039                let buffer_range = range.to_offset(buffer);
5040
5041                excerpt_starts.push(TextSummary::from(expected_text.as_str()));
5042                expected_text.extend(buffer.text_for_range(buffer_range.clone()));
5043                expected_text.push('\n');
5044
5045                let buffer_row_range = buffer.offset_to_point(buffer_range.start).row
5046                    ..=buffer.offset_to_point(buffer_range.end).row;
5047                for row in buffer_row_range {
5048                    expected_buffer_rows.push(Some(row));
5049                }
5050            }
5051            // Remove final trailing newline.
5052            if !expected_excerpts.is_empty() {
5053                expected_text.pop();
5054            }
5055
5056            // Always report one buffer row
5057            if expected_buffer_rows.is_empty() {
5058                expected_buffer_rows.push(Some(0));
5059            }
5060
5061            assert_eq!(snapshot.text(), expected_text);
5062            log::info!("MultiBuffer text: {:?}", expected_text);
5063
5064            assert_eq!(
5065                snapshot.buffer_rows(0).collect::<Vec<_>>(),
5066                expected_buffer_rows,
5067            );
5068
5069            for _ in 0..5 {
5070                let start_row = rng.gen_range(0..=expected_buffer_rows.len());
5071                assert_eq!(
5072                    snapshot.buffer_rows(start_row as u32).collect::<Vec<_>>(),
5073                    &expected_buffer_rows[start_row..],
5074                    "buffer_rows({})",
5075                    start_row
5076                );
5077            }
5078
5079            assert_eq!(
5080                snapshot.max_buffer_row(),
5081                expected_buffer_rows.into_iter().flatten().max().unwrap()
5082            );
5083
5084            let mut excerpt_starts = excerpt_starts.into_iter();
5085            for (buffer, range) in &expected_excerpts {
5086                let buffer = buffer.read(cx);
5087                let buffer_id = buffer.remote_id();
5088                let buffer_range = range.to_offset(buffer);
5089                let buffer_start_point = buffer.offset_to_point(buffer_range.start);
5090                let buffer_start_point_utf16 =
5091                    buffer.text_summary_for_range::<PointUtf16, _>(0..buffer_range.start);
5092
5093                let excerpt_start = excerpt_starts.next().unwrap();
5094                let mut offset = excerpt_start.len;
5095                let mut buffer_offset = buffer_range.start;
5096                let mut point = excerpt_start.lines;
5097                let mut buffer_point = buffer_start_point;
5098                let mut point_utf16 = excerpt_start.lines_utf16();
5099                let mut buffer_point_utf16 = buffer_start_point_utf16;
5100                for ch in buffer
5101                    .snapshot()
5102                    .chunks(buffer_range.clone(), false)
5103                    .flat_map(|c| c.text.chars())
5104                {
5105                    for _ in 0..ch.len_utf8() {
5106                        let left_offset = snapshot.clip_offset(offset, Bias::Left);
5107                        let right_offset = snapshot.clip_offset(offset, Bias::Right);
5108                        let buffer_left_offset = buffer.clip_offset(buffer_offset, Bias::Left);
5109                        let buffer_right_offset = buffer.clip_offset(buffer_offset, Bias::Right);
5110                        assert_eq!(
5111                            left_offset,
5112                            excerpt_start.len + (buffer_left_offset - buffer_range.start),
5113                            "clip_offset({:?}, Left). buffer: {:?}, buffer offset: {:?}",
5114                            offset,
5115                            buffer_id,
5116                            buffer_offset,
5117                        );
5118                        assert_eq!(
5119                            right_offset,
5120                            excerpt_start.len + (buffer_right_offset - buffer_range.start),
5121                            "clip_offset({:?}, Right). buffer: {:?}, buffer offset: {:?}",
5122                            offset,
5123                            buffer_id,
5124                            buffer_offset,
5125                        );
5126
5127                        let left_point = snapshot.clip_point(point, Bias::Left);
5128                        let right_point = snapshot.clip_point(point, Bias::Right);
5129                        let buffer_left_point = buffer.clip_point(buffer_point, Bias::Left);
5130                        let buffer_right_point = buffer.clip_point(buffer_point, Bias::Right);
5131                        assert_eq!(
5132                            left_point,
5133                            excerpt_start.lines + (buffer_left_point - buffer_start_point),
5134                            "clip_point({:?}, Left). buffer: {:?}, buffer point: {:?}",
5135                            point,
5136                            buffer_id,
5137                            buffer_point,
5138                        );
5139                        assert_eq!(
5140                            right_point,
5141                            excerpt_start.lines + (buffer_right_point - buffer_start_point),
5142                            "clip_point({:?}, Right). buffer: {:?}, buffer point: {:?}",
5143                            point,
5144                            buffer_id,
5145                            buffer_point,
5146                        );
5147
5148                        assert_eq!(
5149                            snapshot.point_to_offset(left_point),
5150                            left_offset,
5151                            "point_to_offset({:?})",
5152                            left_point,
5153                        );
5154                        assert_eq!(
5155                            snapshot.offset_to_point(left_offset),
5156                            left_point,
5157                            "offset_to_point({:?})",
5158                            left_offset,
5159                        );
5160
5161                        offset += 1;
5162                        buffer_offset += 1;
5163                        if ch == '\n' {
5164                            point += Point::new(1, 0);
5165                            buffer_point += Point::new(1, 0);
5166                        } else {
5167                            point += Point::new(0, 1);
5168                            buffer_point += Point::new(0, 1);
5169                        }
5170                    }
5171
5172                    for _ in 0..ch.len_utf16() {
5173                        let left_point_utf16 =
5174                            snapshot.clip_point_utf16(Unclipped(point_utf16), Bias::Left);
5175                        let right_point_utf16 =
5176                            snapshot.clip_point_utf16(Unclipped(point_utf16), Bias::Right);
5177                        let buffer_left_point_utf16 =
5178                            buffer.clip_point_utf16(Unclipped(buffer_point_utf16), Bias::Left);
5179                        let buffer_right_point_utf16 =
5180                            buffer.clip_point_utf16(Unclipped(buffer_point_utf16), Bias::Right);
5181                        assert_eq!(
5182                            left_point_utf16,
5183                            excerpt_start.lines_utf16()
5184                                + (buffer_left_point_utf16 - buffer_start_point_utf16),
5185                            "clip_point_utf16({:?}, Left). buffer: {:?}, buffer point_utf16: {:?}",
5186                            point_utf16,
5187                            buffer_id,
5188                            buffer_point_utf16,
5189                        );
5190                        assert_eq!(
5191                            right_point_utf16,
5192                            excerpt_start.lines_utf16()
5193                                + (buffer_right_point_utf16 - buffer_start_point_utf16),
5194                            "clip_point_utf16({:?}, Right). buffer: {:?}, buffer point_utf16: {:?}",
5195                            point_utf16,
5196                            buffer_id,
5197                            buffer_point_utf16,
5198                        );
5199
5200                        if ch == '\n' {
5201                            point_utf16 += PointUtf16::new(1, 0);
5202                            buffer_point_utf16 += PointUtf16::new(1, 0);
5203                        } else {
5204                            point_utf16 += PointUtf16::new(0, 1);
5205                            buffer_point_utf16 += PointUtf16::new(0, 1);
5206                        }
5207                    }
5208                }
5209            }
5210
5211            for (row, line) in expected_text.split('\n').enumerate() {
5212                assert_eq!(
5213                    snapshot.line_len(row as u32),
5214                    line.len() as u32,
5215                    "line_len({}).",
5216                    row
5217                );
5218            }
5219
5220            let text_rope = Rope::from(expected_text.as_str());
5221            for _ in 0..10 {
5222                let end_ix = text_rope.clip_offset(rng.gen_range(0..=text_rope.len()), Bias::Right);
5223                let start_ix = text_rope.clip_offset(rng.gen_range(0..=end_ix), Bias::Left);
5224
5225                let text_for_range = snapshot
5226                    .text_for_range(start_ix..end_ix)
5227                    .collect::<String>();
5228                assert_eq!(
5229                    text_for_range,
5230                    &expected_text[start_ix..end_ix],
5231                    "incorrect text for range {:?}",
5232                    start_ix..end_ix
5233                );
5234
5235                let excerpted_buffer_ranges = multibuffer
5236                    .read(cx)
5237                    .range_to_buffer_ranges(start_ix..end_ix, cx);
5238                let excerpted_buffers_text = excerpted_buffer_ranges
5239                    .iter()
5240                    .map(|(buffer, buffer_range, _)| {
5241                        buffer
5242                            .read(cx)
5243                            .text_for_range(buffer_range.clone())
5244                            .collect::<String>()
5245                    })
5246                    .collect::<Vec<_>>()
5247                    .join("\n");
5248                assert_eq!(excerpted_buffers_text, text_for_range);
5249                if !expected_excerpts.is_empty() {
5250                    assert!(!excerpted_buffer_ranges.is_empty());
5251                }
5252
5253                let expected_summary = TextSummary::from(&expected_text[start_ix..end_ix]);
5254                assert_eq!(
5255                    snapshot.text_summary_for_range::<TextSummary, _>(start_ix..end_ix),
5256                    expected_summary,
5257                    "incorrect summary for range {:?}",
5258                    start_ix..end_ix
5259                );
5260            }
5261
5262            // Anchor resolution
5263            let summaries = snapshot.summaries_for_anchors::<usize, _>(&anchors);
5264            assert_eq!(anchors.len(), summaries.len());
5265            for (anchor, resolved_offset) in anchors.iter().zip(summaries) {
5266                assert!(resolved_offset <= snapshot.len());
5267                assert_eq!(
5268                    snapshot.summary_for_anchor::<usize>(anchor),
5269                    resolved_offset
5270                );
5271            }
5272
5273            for _ in 0..10 {
5274                let end_ix = text_rope.clip_offset(rng.gen_range(0..=text_rope.len()), Bias::Right);
5275                assert_eq!(
5276                    snapshot.reversed_chars_at(end_ix).collect::<String>(),
5277                    expected_text[..end_ix].chars().rev().collect::<String>(),
5278                );
5279            }
5280
5281            for _ in 0..10 {
5282                let end_ix = rng.gen_range(0..=text_rope.len());
5283                let start_ix = rng.gen_range(0..=end_ix);
5284                assert_eq!(
5285                    snapshot
5286                        .bytes_in_range(start_ix..end_ix)
5287                        .flatten()
5288                        .copied()
5289                        .collect::<Vec<_>>(),
5290                    expected_text.as_bytes()[start_ix..end_ix].to_vec(),
5291                    "bytes_in_range({:?})",
5292                    start_ix..end_ix,
5293                );
5294            }
5295        }
5296
5297        let snapshot = multibuffer.read(cx).snapshot(cx);
5298        for (old_snapshot, subscription) in old_versions {
5299            let edits = subscription.consume().into_inner();
5300
5301            log::info!(
5302                "applying subscription edits to old text: {:?}: {:?}",
5303                old_snapshot.text(),
5304                edits,
5305            );
5306
5307            let mut text = old_snapshot.text();
5308            for edit in edits {
5309                let new_text: String = snapshot.text_for_range(edit.new.clone()).collect();
5310                text.replace_range(edit.new.start..edit.new.start + edit.old.len(), &new_text);
5311            }
5312            assert_eq!(text.to_string(), snapshot.text());
5313        }
5314    }
5315
5316    #[gpui::test]
5317    fn test_history(cx: &mut AppContext) {
5318        cx.set_global(SettingsStore::test(cx));
5319
5320        let buffer_1 = cx.add_model(|cx| Buffer::new(0, "1234", cx));
5321        let buffer_2 = cx.add_model(|cx| Buffer::new(0, "5678", cx));
5322        let multibuffer = cx.add_model(|_| MultiBuffer::new(0));
5323        let group_interval = multibuffer.read(cx).history.group_interval;
5324        multibuffer.update(cx, |multibuffer, cx| {
5325            multibuffer.push_excerpts(
5326                buffer_1.clone(),
5327                [ExcerptRange {
5328                    context: 0..buffer_1.read(cx).len(),
5329                    primary: None,
5330                }],
5331                cx,
5332            );
5333            multibuffer.push_excerpts(
5334                buffer_2.clone(),
5335                [ExcerptRange {
5336                    context: 0..buffer_2.read(cx).len(),
5337                    primary: None,
5338                }],
5339                cx,
5340            );
5341        });
5342
5343        let mut now = Instant::now();
5344
5345        multibuffer.update(cx, |multibuffer, cx| {
5346            let transaction_1 = multibuffer.start_transaction_at(now, cx).unwrap();
5347            multibuffer.edit(
5348                [
5349                    (Point::new(0, 0)..Point::new(0, 0), "A"),
5350                    (Point::new(1, 0)..Point::new(1, 0), "A"),
5351                ],
5352                None,
5353                cx,
5354            );
5355            multibuffer.edit(
5356                [
5357                    (Point::new(0, 1)..Point::new(0, 1), "B"),
5358                    (Point::new(1, 1)..Point::new(1, 1), "B"),
5359                ],
5360                None,
5361                cx,
5362            );
5363            multibuffer.end_transaction_at(now, cx);
5364            assert_eq!(multibuffer.read(cx).text(), "AB1234\nAB5678");
5365
5366            // Edit buffer 1 through the multibuffer
5367            now += 2 * group_interval;
5368            multibuffer.start_transaction_at(now, cx);
5369            multibuffer.edit([(2..2, "C")], None, cx);
5370            multibuffer.end_transaction_at(now, cx);
5371            assert_eq!(multibuffer.read(cx).text(), "ABC1234\nAB5678");
5372
5373            // Edit buffer 1 independently
5374            buffer_1.update(cx, |buffer_1, cx| {
5375                buffer_1.start_transaction_at(now);
5376                buffer_1.edit([(3..3, "D")], None, cx);
5377                buffer_1.end_transaction_at(now, cx);
5378
5379                now += 2 * group_interval;
5380                buffer_1.start_transaction_at(now);
5381                buffer_1.edit([(4..4, "E")], None, cx);
5382                buffer_1.end_transaction_at(now, cx);
5383            });
5384            assert_eq!(multibuffer.read(cx).text(), "ABCDE1234\nAB5678");
5385
5386            // An undo in the multibuffer undoes the multibuffer transaction
5387            // and also any individual buffer edits that have occurred since
5388            // that transaction.
5389            multibuffer.undo(cx);
5390            assert_eq!(multibuffer.read(cx).text(), "AB1234\nAB5678");
5391
5392            multibuffer.undo(cx);
5393            assert_eq!(multibuffer.read(cx).text(), "1234\n5678");
5394
5395            multibuffer.redo(cx);
5396            assert_eq!(multibuffer.read(cx).text(), "AB1234\nAB5678");
5397
5398            multibuffer.redo(cx);
5399            assert_eq!(multibuffer.read(cx).text(), "ABCDE1234\nAB5678");
5400
5401            // Undo buffer 2 independently.
5402            buffer_2.update(cx, |buffer_2, cx| buffer_2.undo(cx));
5403            assert_eq!(multibuffer.read(cx).text(), "ABCDE1234\n5678");
5404
5405            // An undo in the multibuffer undoes the components of the
5406            // the last multibuffer transaction that are not already undone.
5407            multibuffer.undo(cx);
5408            assert_eq!(multibuffer.read(cx).text(), "AB1234\n5678");
5409
5410            multibuffer.undo(cx);
5411            assert_eq!(multibuffer.read(cx).text(), "1234\n5678");
5412
5413            multibuffer.redo(cx);
5414            assert_eq!(multibuffer.read(cx).text(), "AB1234\nAB5678");
5415
5416            buffer_1.update(cx, |buffer_1, cx| buffer_1.redo(cx));
5417            assert_eq!(multibuffer.read(cx).text(), "ABCD1234\nAB5678");
5418
5419            // Redo stack gets cleared after an edit.
5420            now += 2 * group_interval;
5421            multibuffer.start_transaction_at(now, cx);
5422            multibuffer.edit([(0..0, "X")], None, cx);
5423            multibuffer.end_transaction_at(now, cx);
5424            assert_eq!(multibuffer.read(cx).text(), "XABCD1234\nAB5678");
5425            multibuffer.redo(cx);
5426            assert_eq!(multibuffer.read(cx).text(), "XABCD1234\nAB5678");
5427            multibuffer.undo(cx);
5428            assert_eq!(multibuffer.read(cx).text(), "ABCD1234\nAB5678");
5429            multibuffer.undo(cx);
5430            assert_eq!(multibuffer.read(cx).text(), "1234\n5678");
5431
5432            // Transactions can be grouped manually.
5433            multibuffer.redo(cx);
5434            multibuffer.redo(cx);
5435            assert_eq!(multibuffer.read(cx).text(), "XABCD1234\nAB5678");
5436            multibuffer.group_until_transaction(transaction_1, cx);
5437            multibuffer.undo(cx);
5438            assert_eq!(multibuffer.read(cx).text(), "1234\n5678");
5439            multibuffer.redo(cx);
5440            assert_eq!(multibuffer.read(cx).text(), "XABCD1234\nAB5678");
5441        });
5442    }
5443}