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