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