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