multi_buffer.rs

   1mod anchor;
   2
   3pub use anchor::{Anchor, AnchorRangeExt};
   4use anyhow::Result;
   5use clock::ReplicaId;
   6use collections::{Bound, HashMap, HashSet};
   7use gpui::{AppContext, Entity, ModelContext, ModelHandle, Task};
   8pub use language::Completion;
   9use language::{
  10    Buffer, BufferChunks, BufferSnapshot, Chunk, DiagnosticEntry, Event, File, Language, Outline,
  11    OutlineItem, Selection, ToOffset as _, ToPoint as _, ToPointUtf16 as _, TransactionId,
  12};
  13use std::{
  14    cell::{Ref, RefCell},
  15    cmp, fmt, io,
  16    iter::{self, FromIterator},
  17    ops::{Range, RangeBounds, Sub},
  18    str,
  19    sync::Arc,
  20    time::{Duration, Instant},
  21};
  22use sum_tree::{Bias, Cursor, SumTree};
  23use text::{
  24    locator::Locator,
  25    rope::TextDimension,
  26    subscription::{Subscription, Topic},
  27    AnchorRangeExt as _, Edit, Point, PointUtf16, TextSummary,
  28};
  29use theme::SyntaxTheme;
  30
  31const NEWLINES: &'static [u8] = &[b'\n'; u8::MAX as usize];
  32
  33pub type ExcerptId = Locator;
  34
  35pub struct MultiBuffer {
  36    snapshot: RefCell<MultiBufferSnapshot>,
  37    buffers: RefCell<HashMap<usize, BufferState>>,
  38    subscriptions: Topic,
  39    singleton: bool,
  40    replica_id: ReplicaId,
  41    history: History,
  42    title: Option<String>,
  43}
  44
  45struct History {
  46    next_transaction_id: TransactionId,
  47    undo_stack: Vec<Transaction>,
  48    redo_stack: Vec<Transaction>,
  49    transaction_depth: usize,
  50    group_interval: Duration,
  51}
  52
  53#[derive(Copy, Clone, Eq, PartialEq, PartialOrd, Ord, Debug)]
  54pub enum CharKind {
  55    Newline,
  56    Punctuation,
  57    Whitespace,
  58    Word,
  59}
  60
  61struct Transaction {
  62    id: TransactionId,
  63    buffer_transactions: HashSet<(usize, text::TransactionId)>,
  64    first_edit_at: Instant,
  65    last_edit_at: Instant,
  66}
  67
  68pub trait ToOffset: 'static + fmt::Debug {
  69    fn to_offset(&self, snapshot: &MultiBufferSnapshot) -> usize;
  70}
  71
  72pub trait ToPoint: 'static + fmt::Debug {
  73    fn to_point(&self, snapshot: &MultiBufferSnapshot) -> Point;
  74}
  75
  76pub trait ToPointUtf16: 'static + fmt::Debug {
  77    fn to_point_utf16(&self, snapshot: &MultiBufferSnapshot) -> PointUtf16;
  78}
  79
  80struct BufferState {
  81    buffer: ModelHandle<Buffer>,
  82    last_version: clock::Global,
  83    last_parse_count: usize,
  84    last_selections_update_count: usize,
  85    last_diagnostics_update_count: usize,
  86    last_file_update_count: usize,
  87    excerpts: Vec<ExcerptId>,
  88    _subscriptions: [gpui::Subscription; 2],
  89}
  90
  91#[derive(Clone, Default)]
  92pub struct MultiBufferSnapshot {
  93    singleton: bool,
  94    excerpts: SumTree<Excerpt>,
  95    parse_count: usize,
  96    diagnostics_update_count: usize,
  97    trailing_excerpt_update_count: usize,
  98    is_dirty: bool,
  99    has_conflict: bool,
 100}
 101
 102pub struct ExcerptBoundary {
 103    pub row: u32,
 104    pub buffer: BufferSnapshot,
 105    pub range: Range<text::Anchor>,
 106    pub starts_new_buffer: bool,
 107}
 108
 109#[derive(Clone)]
 110struct Excerpt {
 111    id: ExcerptId,
 112    buffer_id: usize,
 113    buffer: BufferSnapshot,
 114    range: Range<text::Anchor>,
 115    max_buffer_row: u32,
 116    text_summary: TextSummary,
 117    has_trailing_newline: bool,
 118}
 119
 120#[derive(Clone, Debug, Default)]
 121struct ExcerptSummary {
 122    excerpt_id: ExcerptId,
 123    max_buffer_row: u32,
 124    text: TextSummary,
 125}
 126
 127pub struct MultiBufferRows<'a> {
 128    buffer_row_range: Range<u32>,
 129    excerpts: Cursor<'a, Excerpt, Point>,
 130}
 131
 132pub struct MultiBufferChunks<'a> {
 133    range: Range<usize>,
 134    excerpts: Cursor<'a, Excerpt, usize>,
 135    excerpt_chunks: Option<ExcerptChunks<'a>>,
 136    language_aware: bool,
 137}
 138
 139pub struct MultiBufferBytes<'a> {
 140    range: Range<usize>,
 141    excerpts: Cursor<'a, Excerpt, usize>,
 142    excerpt_bytes: Option<ExcerptBytes<'a>>,
 143    chunk: &'a [u8],
 144}
 145
 146struct ExcerptChunks<'a> {
 147    content_chunks: BufferChunks<'a>,
 148    footer_height: usize,
 149}
 150
 151struct ExcerptBytes<'a> {
 152    content_bytes: language::rope::Bytes<'a>,
 153    footer_height: usize,
 154}
 155
 156impl MultiBuffer {
 157    pub fn new(replica_id: ReplicaId) -> Self {
 158        Self {
 159            snapshot: Default::default(),
 160            buffers: Default::default(),
 161            subscriptions: Default::default(),
 162            singleton: false,
 163            replica_id,
 164            history: History {
 165                next_transaction_id: Default::default(),
 166                undo_stack: Default::default(),
 167                redo_stack: Default::default(),
 168                transaction_depth: 0,
 169                group_interval: Duration::from_millis(300),
 170            },
 171            title: Default::default(),
 172        }
 173    }
 174
 175    pub fn with_title(mut self, title: String) -> Self {
 176        self.title = Some(title);
 177        self
 178    }
 179
 180    pub fn singleton(buffer: ModelHandle<Buffer>, cx: &mut ModelContext<Self>) -> Self {
 181        let mut this = Self::new(buffer.read(cx).replica_id());
 182        this.singleton = true;
 183        this.push_excerpts(buffer, [text::Anchor::min()..text::Anchor::max()], cx);
 184        this.snapshot.borrow_mut().singleton = true;
 185        this
 186    }
 187
 188    #[cfg(any(test, feature = "test-support"))]
 189    pub fn build_simple(text: &str, cx: &mut gpui::MutableAppContext) -> ModelHandle<Self> {
 190        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx));
 191        cx.add_model(|cx| Self::singleton(buffer, cx))
 192    }
 193
 194    #[cfg(any(test, feature = "test-support"))]
 195    pub fn build_random(
 196        rng: &mut impl rand::Rng,
 197        cx: &mut gpui::MutableAppContext,
 198    ) -> ModelHandle<Self> {
 199        cx.add_model(|cx| {
 200            let mut multibuffer = MultiBuffer::new(0);
 201            let mutation_count = rng.gen_range(1..=5);
 202            multibuffer.randomly_edit_excerpts(rng, mutation_count, cx);
 203            multibuffer
 204        })
 205    }
 206
 207    pub fn replica_id(&self) -> ReplicaId {
 208        self.replica_id
 209    }
 210
 211    pub fn snapshot(&self, cx: &AppContext) -> MultiBufferSnapshot {
 212        self.sync(cx);
 213        self.snapshot.borrow().clone()
 214    }
 215
 216    pub fn read(&self, cx: &AppContext) -> Ref<MultiBufferSnapshot> {
 217        self.sync(cx);
 218        self.snapshot.borrow()
 219    }
 220
 221    pub fn as_singleton(&self) -> Option<ModelHandle<Buffer>> {
 222        if self.singleton {
 223            return Some(
 224                self.buffers
 225                    .borrow()
 226                    .values()
 227                    .next()
 228                    .unwrap()
 229                    .buffer
 230                    .clone(),
 231            );
 232        } else {
 233            None
 234        }
 235    }
 236
 237    pub fn is_singleton(&self) -> bool {
 238        self.singleton
 239    }
 240
 241    pub fn subscribe(&mut self) -> Subscription {
 242        self.subscriptions.subscribe()
 243    }
 244
 245    pub fn edit<I, S, T>(&mut self, ranges: I, new_text: T, cx: &mut ModelContext<Self>)
 246    where
 247        I: IntoIterator<Item = Range<S>>,
 248        S: ToOffset,
 249        T: Into<String>,
 250    {
 251        self.edit_internal(ranges, new_text, false, cx)
 252    }
 253
 254    pub fn edit_with_autoindent<I, S, T>(
 255        &mut self,
 256        ranges: I,
 257        new_text: T,
 258        cx: &mut ModelContext<Self>,
 259    ) where
 260        I: IntoIterator<Item = Range<S>>,
 261        S: ToOffset,
 262        T: Into<String>,
 263    {
 264        self.edit_internal(ranges, new_text, true, cx)
 265    }
 266
 267    pub fn edit_internal<I, S, T>(
 268        &mut self,
 269        ranges_iter: I,
 270        new_text: T,
 271        autoindent: bool,
 272        cx: &mut ModelContext<Self>,
 273    ) where
 274        I: IntoIterator<Item = Range<S>>,
 275        S: ToOffset,
 276        T: Into<String>,
 277    {
 278        if self.buffers.borrow().is_empty() {
 279            return;
 280        }
 281
 282        if let Some(buffer) = self.as_singleton() {
 283            let snapshot = self.read(cx);
 284            let ranges = ranges_iter
 285                .into_iter()
 286                .map(|range| range.start.to_offset(&snapshot)..range.end.to_offset(&snapshot));
 287            return buffer.update(cx, |buffer, cx| {
 288                if autoindent {
 289                    buffer.edit_with_autoindent(ranges, new_text, cx);
 290                } else {
 291                    buffer.edit(ranges, new_text, cx);
 292                }
 293            });
 294        }
 295
 296        let snapshot = self.read(cx);
 297        let mut buffer_edits: HashMap<usize, Vec<(Range<usize>, bool)>> = Default::default();
 298        let mut cursor = snapshot.excerpts.cursor::<usize>();
 299        for range in ranges_iter {
 300            let start = range.start.to_offset(&snapshot);
 301            let end = range.end.to_offset(&snapshot);
 302            cursor.seek(&start, Bias::Right, &());
 303            if cursor.item().is_none() && start == *cursor.start() {
 304                cursor.prev(&());
 305            }
 306            let start_excerpt = cursor.item().expect("start offset out of bounds");
 307            let start_overshoot = start - cursor.start();
 308            let buffer_start =
 309                start_excerpt.range.start.to_offset(&start_excerpt.buffer) + start_overshoot;
 310
 311            cursor.seek(&end, Bias::Right, &());
 312            if cursor.item().is_none() && end == *cursor.start() {
 313                cursor.prev(&());
 314            }
 315            let end_excerpt = cursor.item().expect("end offset out of bounds");
 316            let end_overshoot = end - cursor.start();
 317            let buffer_end = end_excerpt.range.start.to_offset(&end_excerpt.buffer) + end_overshoot;
 318
 319            if start_excerpt.id == end_excerpt.id {
 320                buffer_edits
 321                    .entry(start_excerpt.buffer_id)
 322                    .or_insert(Vec::new())
 323                    .push((buffer_start..buffer_end, true));
 324            } else {
 325                let start_excerpt_range =
 326                    buffer_start..start_excerpt.range.end.to_offset(&start_excerpt.buffer);
 327                let end_excerpt_range =
 328                    end_excerpt.range.start.to_offset(&end_excerpt.buffer)..buffer_end;
 329                buffer_edits
 330                    .entry(start_excerpt.buffer_id)
 331                    .or_insert(Vec::new())
 332                    .push((start_excerpt_range, true));
 333                buffer_edits
 334                    .entry(end_excerpt.buffer_id)
 335                    .or_insert(Vec::new())
 336                    .push((end_excerpt_range, false));
 337
 338                cursor.seek(&start, Bias::Right, &());
 339                cursor.next(&());
 340                while let Some(excerpt) = cursor.item() {
 341                    if excerpt.id == end_excerpt.id {
 342                        break;
 343                    }
 344                    buffer_edits
 345                        .entry(excerpt.buffer_id)
 346                        .or_insert(Vec::new())
 347                        .push((excerpt.range.to_offset(&excerpt.buffer), false));
 348                    cursor.next(&());
 349                }
 350            }
 351        }
 352
 353        let new_text = new_text.into();
 354        for (buffer_id, mut edits) in buffer_edits {
 355            edits.sort_unstable_by_key(|(range, _)| range.start);
 356            self.buffers.borrow()[&buffer_id]
 357                .buffer
 358                .update(cx, |buffer, cx| {
 359                    let mut edits = edits.into_iter().peekable();
 360                    let mut insertions = Vec::new();
 361                    let mut deletions = Vec::new();
 362                    while let Some((mut range, mut is_insertion)) = edits.next() {
 363                        while let Some((next_range, next_is_insertion)) = edits.peek() {
 364                            if range.end >= next_range.start {
 365                                range.end = cmp::max(next_range.end, range.end);
 366                                is_insertion |= *next_is_insertion;
 367                                edits.next();
 368                            } else {
 369                                break;
 370                            }
 371                        }
 372
 373                        if is_insertion {
 374                            insertions.push(
 375                                buffer.anchor_before(range.start)..buffer.anchor_before(range.end),
 376                            );
 377                        } else if !range.is_empty() {
 378                            deletions.push(
 379                                buffer.anchor_before(range.start)..buffer.anchor_before(range.end),
 380                            );
 381                        }
 382                    }
 383
 384                    if autoindent {
 385                        buffer.edit_with_autoindent(deletions, "", cx);
 386                        buffer.edit_with_autoindent(insertions, new_text.clone(), cx);
 387                    } else {
 388                        buffer.edit(deletions, "", cx);
 389                        buffer.edit(insertions, new_text.clone(), cx);
 390                    }
 391                })
 392        }
 393    }
 394
 395    pub fn start_transaction(&mut self, cx: &mut ModelContext<Self>) -> Option<TransactionId> {
 396        self.start_transaction_at(Instant::now(), cx)
 397    }
 398
 399    pub(crate) fn start_transaction_at(
 400        &mut self,
 401        now: Instant,
 402        cx: &mut ModelContext<Self>,
 403    ) -> Option<TransactionId> {
 404        if let Some(buffer) = self.as_singleton() {
 405            return buffer.update(cx, |buffer, _| buffer.start_transaction_at(now));
 406        }
 407
 408        for BufferState { buffer, .. } in self.buffers.borrow().values() {
 409            buffer.update(cx, |buffer, _| buffer.start_transaction_at(now));
 410        }
 411        self.history.start_transaction(now)
 412    }
 413
 414    pub fn end_transaction(&mut self, cx: &mut ModelContext<Self>) -> Option<TransactionId> {
 415        self.end_transaction_at(Instant::now(), cx)
 416    }
 417
 418    pub(crate) fn end_transaction_at(
 419        &mut self,
 420        now: Instant,
 421        cx: &mut ModelContext<Self>,
 422    ) -> Option<TransactionId> {
 423        if let Some(buffer) = self.as_singleton() {
 424            return buffer.update(cx, |buffer, cx| buffer.end_transaction_at(now, cx));
 425        }
 426
 427        let mut buffer_transactions = HashSet::default();
 428        for BufferState { buffer, .. } in self.buffers.borrow().values() {
 429            if let Some(transaction_id) =
 430                buffer.update(cx, |buffer, cx| buffer.end_transaction_at(now, cx))
 431            {
 432                buffer_transactions.insert((buffer.id(), transaction_id));
 433            }
 434        }
 435
 436        if self.history.end_transaction(now, buffer_transactions) {
 437            let transaction_id = self.history.group().unwrap();
 438            Some(transaction_id)
 439        } else {
 440            None
 441        }
 442    }
 443
 444    pub fn finalize_last_transaction(&mut self, cx: &mut ModelContext<Self>) {
 445        for BufferState { buffer, .. } in self.buffers.borrow().values() {
 446            buffer.update(cx, |buffer, _| {
 447                buffer.finalize_last_transaction();
 448            });
 449        }
 450    }
 451
 452    pub fn set_active_selections(
 453        &mut self,
 454        selections: &[Selection<Anchor>],
 455        cx: &mut ModelContext<Self>,
 456    ) {
 457        let mut selections_by_buffer: HashMap<usize, Vec<Selection<text::Anchor>>> =
 458            Default::default();
 459        let snapshot = self.read(cx);
 460        let mut cursor = snapshot.excerpts.cursor::<Option<&ExcerptId>>();
 461        for selection in selections {
 462            cursor.seek(&Some(&selection.start.excerpt_id), Bias::Left, &());
 463            while let Some(excerpt) = cursor.item() {
 464                if excerpt.id > selection.end.excerpt_id {
 465                    break;
 466                }
 467
 468                let mut start = excerpt.range.start.clone();
 469                let mut end = excerpt.range.end.clone();
 470                if excerpt.id == selection.start.excerpt_id {
 471                    start = selection.start.text_anchor.clone();
 472                }
 473                if excerpt.id == selection.end.excerpt_id {
 474                    end = selection.end.text_anchor.clone();
 475                }
 476                selections_by_buffer
 477                    .entry(excerpt.buffer_id)
 478                    .or_default()
 479                    .push(Selection {
 480                        id: selection.id,
 481                        start,
 482                        end,
 483                        reversed: selection.reversed,
 484                        goal: selection.goal,
 485                    });
 486
 487                cursor.next(&());
 488            }
 489        }
 490
 491        for (buffer_id, buffer_state) in self.buffers.borrow().iter() {
 492            if !selections_by_buffer.contains_key(buffer_id) {
 493                buffer_state
 494                    .buffer
 495                    .update(cx, |buffer, cx| buffer.remove_active_selections(cx));
 496            }
 497        }
 498
 499        for (buffer_id, mut selections) in selections_by_buffer {
 500            self.buffers.borrow()[&buffer_id]
 501                .buffer
 502                .update(cx, |buffer, cx| {
 503                    selections.sort_unstable_by(|a, b| a.start.cmp(&b.start, buffer).unwrap());
 504                    let mut selections = selections.into_iter().peekable();
 505                    let merged_selections = Arc::from_iter(iter::from_fn(|| {
 506                        let mut selection = selections.next()?;
 507                        while let Some(next_selection) = selections.peek() {
 508                            if selection
 509                                .end
 510                                .cmp(&next_selection.start, buffer)
 511                                .unwrap()
 512                                .is_ge()
 513                            {
 514                                let next_selection = selections.next().unwrap();
 515                                if next_selection
 516                                    .end
 517                                    .cmp(&selection.end, buffer)
 518                                    .unwrap()
 519                                    .is_ge()
 520                                {
 521                                    selection.end = next_selection.end;
 522                                }
 523                            } else {
 524                                break;
 525                            }
 526                        }
 527                        Some(selection)
 528                    }));
 529                    buffer.set_active_selections(merged_selections, cx);
 530                });
 531        }
 532    }
 533
 534    pub fn remove_active_selections(&mut self, cx: &mut ModelContext<Self>) {
 535        for buffer in self.buffers.borrow().values() {
 536            buffer
 537                .buffer
 538                .update(cx, |buffer, cx| buffer.remove_active_selections(cx));
 539        }
 540    }
 541
 542    pub fn undo(&mut self, cx: &mut ModelContext<Self>) -> Option<TransactionId> {
 543        if let Some(buffer) = self.as_singleton() {
 544            return buffer.update(cx, |buffer, cx| buffer.undo(cx));
 545        }
 546
 547        while let Some(transaction) = self.history.pop_undo() {
 548            let mut undone = false;
 549            for (buffer_id, buffer_transaction_id) in &transaction.buffer_transactions {
 550                if let Some(BufferState { buffer, .. }) = self.buffers.borrow().get(&buffer_id) {
 551                    undone |= buffer.update(cx, |buf, cx| {
 552                        buf.undo_transaction(*buffer_transaction_id, cx)
 553                    });
 554                }
 555            }
 556
 557            if undone {
 558                return Some(transaction.id);
 559            }
 560        }
 561
 562        None
 563    }
 564
 565    pub fn redo(&mut self, cx: &mut ModelContext<Self>) -> Option<TransactionId> {
 566        if let Some(buffer) = self.as_singleton() {
 567            return buffer.update(cx, |buffer, cx| buffer.redo(cx));
 568        }
 569
 570        while let Some(transaction) = self.history.pop_redo() {
 571            let mut redone = false;
 572            for (buffer_id, buffer_transaction_id) in &transaction.buffer_transactions {
 573                if let Some(BufferState { buffer, .. }) = self.buffers.borrow().get(&buffer_id) {
 574                    redone |= buffer.update(cx, |buf, cx| {
 575                        buf.redo_transaction(*buffer_transaction_id, cx)
 576                    });
 577                }
 578            }
 579
 580            if redone {
 581                return Some(transaction.id);
 582            }
 583        }
 584
 585        None
 586    }
 587
 588    pub fn push_excerpts<O>(
 589        &mut self,
 590        buffer: ModelHandle<Buffer>,
 591        ranges: impl IntoIterator<Item = Range<O>>,
 592        cx: &mut ModelContext<Self>,
 593    ) -> Vec<ExcerptId>
 594    where
 595        O: text::ToOffset,
 596    {
 597        self.insert_excerpts_after(&ExcerptId::max(), buffer, ranges, cx)
 598    }
 599
 600    pub fn push_excerpts_with_context_lines<O>(
 601        &mut self,
 602        buffer: ModelHandle<Buffer>,
 603        ranges: Vec<Range<O>>,
 604        context_line_count: u32,
 605        cx: &mut ModelContext<Self>,
 606    ) -> Vec<Range<Anchor>>
 607    where
 608        O: text::ToPoint + text::ToOffset,
 609    {
 610        let buffer_id = buffer.id();
 611        let buffer_snapshot = buffer.read(cx).snapshot();
 612        let max_point = buffer_snapshot.max_point();
 613
 614        let mut range_counts = Vec::new();
 615        let mut excerpt_ranges = Vec::new();
 616        let mut range_iter = ranges
 617            .iter()
 618            .map(|range| {
 619                range.start.to_point(&buffer_snapshot)..range.end.to_point(&buffer_snapshot)
 620            })
 621            .peekable();
 622        while let Some(range) = range_iter.next() {
 623            let excerpt_start = Point::new(range.start.row.saturating_sub(context_line_count), 0);
 624            let mut excerpt_end =
 625                Point::new(range.end.row + 1 + context_line_count, 0).min(max_point);
 626            let mut ranges_in_excerpt = 1;
 627
 628            while let Some(next_range) = range_iter.peek() {
 629                if next_range.start.row <= excerpt_end.row + context_line_count {
 630                    excerpt_end =
 631                        Point::new(next_range.end.row + 1 + context_line_count, 0).min(max_point);
 632                    ranges_in_excerpt += 1;
 633                    range_iter.next();
 634                } else {
 635                    break;
 636                }
 637            }
 638
 639            excerpt_ranges.push(excerpt_start..excerpt_end);
 640            range_counts.push(ranges_in_excerpt);
 641        }
 642
 643        let excerpt_ids = self.push_excerpts(buffer, excerpt_ranges, cx);
 644
 645        let mut anchor_ranges = Vec::new();
 646        let mut ranges = ranges.into_iter();
 647        for (excerpt_id, range_count) in excerpt_ids.into_iter().zip(range_counts.into_iter()) {
 648            anchor_ranges.extend(ranges.by_ref().take(range_count).map(|range| {
 649                let start = Anchor {
 650                    buffer_id,
 651                    excerpt_id: excerpt_id.clone(),
 652                    text_anchor: buffer_snapshot.anchor_after(range.start),
 653                };
 654                let end = Anchor {
 655                    buffer_id,
 656                    excerpt_id: excerpt_id.clone(),
 657                    text_anchor: buffer_snapshot.anchor_after(range.end),
 658                };
 659                start..end
 660            }))
 661        }
 662        anchor_ranges
 663    }
 664
 665    pub fn insert_excerpts_after<O>(
 666        &mut self,
 667        prev_excerpt_id: &ExcerptId,
 668        buffer: ModelHandle<Buffer>,
 669        ranges: impl IntoIterator<Item = Range<O>>,
 670        cx: &mut ModelContext<Self>,
 671    ) -> Vec<ExcerptId>
 672    where
 673        O: text::ToOffset,
 674    {
 675        assert_eq!(self.history.transaction_depth, 0);
 676        self.sync(cx);
 677
 678        let buffer_id = buffer.id();
 679        let buffer_snapshot = buffer.read(cx).snapshot();
 680
 681        let mut buffers = self.buffers.borrow_mut();
 682        let buffer_state = buffers.entry(buffer_id).or_insert_with(|| BufferState {
 683            last_version: buffer_snapshot.version().clone(),
 684            last_parse_count: buffer_snapshot.parse_count(),
 685            last_selections_update_count: buffer_snapshot.selections_update_count(),
 686            last_diagnostics_update_count: buffer_snapshot.diagnostics_update_count(),
 687            last_file_update_count: buffer_snapshot.file_update_count(),
 688            excerpts: Default::default(),
 689            _subscriptions: [
 690                cx.observe(&buffer, |_, _, cx| cx.notify()),
 691                cx.subscribe(&buffer, Self::on_buffer_event),
 692            ],
 693            buffer,
 694        });
 695
 696        let mut snapshot = self.snapshot.borrow_mut();
 697        let mut cursor = snapshot.excerpts.cursor::<Option<&ExcerptId>>();
 698        let mut new_excerpts = cursor.slice(&Some(prev_excerpt_id), Bias::Right, &());
 699
 700        let mut prev_id = ExcerptId::min();
 701        let edit_start = new_excerpts.summary().text.bytes;
 702        new_excerpts.update_last(
 703            |excerpt| {
 704                excerpt.has_trailing_newline = true;
 705                prev_id = excerpt.id.clone();
 706            },
 707            &(),
 708        );
 709
 710        let mut next_id = ExcerptId::max();
 711        if let Some(next_excerpt) = cursor.item() {
 712            next_id = next_excerpt.id.clone();
 713        }
 714
 715        let mut ids = Vec::new();
 716        let mut ranges = ranges.into_iter().peekable();
 717        while let Some(range) = ranges.next() {
 718            let id = ExcerptId::between(&prev_id, &next_id);
 719            if let Err(ix) = buffer_state.excerpts.binary_search(&id) {
 720                buffer_state.excerpts.insert(ix, id.clone());
 721            }
 722            let range = buffer_snapshot.anchor_before(&range.start)
 723                ..buffer_snapshot.anchor_after(&range.end);
 724            let excerpt = Excerpt::new(
 725                id.clone(),
 726                buffer_id,
 727                buffer_snapshot.clone(),
 728                range,
 729                ranges.peek().is_some() || cursor.item().is_some(),
 730            );
 731            new_excerpts.push(excerpt, &());
 732            prev_id = id.clone();
 733            ids.push(id);
 734        }
 735
 736        let edit_end = new_excerpts.summary().text.bytes;
 737
 738        let suffix = cursor.suffix(&());
 739        let changed_trailing_excerpt = suffix.is_empty();
 740        new_excerpts.push_tree(suffix, &());
 741        drop(cursor);
 742        snapshot.excerpts = new_excerpts;
 743        if changed_trailing_excerpt {
 744            snapshot.trailing_excerpt_update_count += 1;
 745        }
 746
 747        self.subscriptions.publish_mut([Edit {
 748            old: edit_start..edit_start,
 749            new: edit_start..edit_end,
 750        }]);
 751
 752        cx.notify();
 753        ids
 754    }
 755
 756    pub fn excerpt_ids_for_buffer(&self, buffer: &ModelHandle<Buffer>) -> Vec<ExcerptId> {
 757        self.buffers
 758            .borrow()
 759            .get(&buffer.id())
 760            .map_or(Vec::new(), |state| state.excerpts.clone())
 761    }
 762
 763    pub fn excerpted_buffers<'a, T: ToOffset>(
 764        &'a self,
 765        range: Range<T>,
 766        cx: &AppContext,
 767    ) -> Vec<(ModelHandle<Buffer>, Range<usize>)> {
 768        let snapshot = self.snapshot(cx);
 769        let start = range.start.to_offset(&snapshot);
 770        let end = range.end.to_offset(&snapshot);
 771
 772        let mut result = Vec::new();
 773        let mut cursor = snapshot.excerpts.cursor::<usize>();
 774        cursor.seek(&start, Bias::Right, &());
 775        while let Some(excerpt) = cursor.item() {
 776            if *cursor.start() > end {
 777                break;
 778            }
 779
 780            let mut end_before_newline = cursor.end(&());
 781            if excerpt.has_trailing_newline {
 782                end_before_newline -= 1;
 783            }
 784            let excerpt_start = excerpt.range.start.to_offset(&excerpt.buffer);
 785            let start = excerpt_start + (cmp::max(start, *cursor.start()) - *cursor.start());
 786            let end = excerpt_start + (cmp::min(end, end_before_newline) - *cursor.start());
 787            let buffer = self.buffers.borrow()[&excerpt.buffer_id].buffer.clone();
 788            result.push((buffer, start..end));
 789            cursor.next(&());
 790        }
 791
 792        result
 793    }
 794
 795    pub fn remove_excerpts<'a>(
 796        &mut self,
 797        excerpt_ids: impl IntoIterator<Item = &'a ExcerptId>,
 798        cx: &mut ModelContext<Self>,
 799    ) {
 800        let mut buffers = self.buffers.borrow_mut();
 801        let mut snapshot = self.snapshot.borrow_mut();
 802        let mut new_excerpts = SumTree::new();
 803        let mut cursor = snapshot.excerpts.cursor::<(Option<&ExcerptId>, usize)>();
 804        let mut edits = Vec::new();
 805        let mut excerpt_ids = excerpt_ids.into_iter().peekable();
 806
 807        while let Some(mut excerpt_id) = excerpt_ids.next() {
 808            // Seek to the next excerpt to remove, preserving any preceding excerpts.
 809            new_excerpts.push_tree(cursor.slice(&Some(excerpt_id), Bias::Left, &()), &());
 810            if let Some(mut excerpt) = cursor.item() {
 811                if excerpt.id != *excerpt_id {
 812                    continue;
 813                }
 814                let mut old_start = cursor.start().1;
 815
 816                // Skip over the removed excerpt.
 817                loop {
 818                    if let Some(buffer_state) = buffers.get_mut(&excerpt.buffer_id) {
 819                        buffer_state.excerpts.retain(|id| id != excerpt_id);
 820                        if buffer_state.excerpts.is_empty() {
 821                            buffers.remove(&excerpt.buffer_id);
 822                        }
 823                    }
 824                    cursor.next(&());
 825
 826                    // Skip over any subsequent excerpts that are also removed.
 827                    if let Some(&next_excerpt_id) = excerpt_ids.peek() {
 828                        if let Some(next_excerpt) = cursor.item() {
 829                            if next_excerpt.id == *next_excerpt_id {
 830                                excerpt = next_excerpt;
 831                                excerpt_id = excerpt_ids.next().unwrap();
 832                                continue;
 833                            }
 834                        }
 835                    }
 836
 837                    break;
 838                }
 839
 840                // When removing the last excerpt, remove the trailing newline from
 841                // the previous excerpt.
 842                if cursor.item().is_none() && old_start > 0 {
 843                    old_start -= 1;
 844                    new_excerpts.update_last(|e| e.has_trailing_newline = false, &());
 845                }
 846
 847                // Push an edit for the removal of this run of excerpts.
 848                let old_end = cursor.start().1;
 849                let new_start = new_excerpts.summary().text.bytes;
 850                edits.push(Edit {
 851                    old: old_start..old_end,
 852                    new: new_start..new_start,
 853                });
 854            }
 855        }
 856        let suffix = cursor.suffix(&());
 857        let changed_trailing_excerpt = suffix.is_empty();
 858        new_excerpts.push_tree(suffix, &());
 859        drop(cursor);
 860        snapshot.excerpts = new_excerpts;
 861        if changed_trailing_excerpt {
 862            snapshot.trailing_excerpt_update_count += 1;
 863        }
 864
 865        self.subscriptions.publish_mut(edits);
 866        cx.notify();
 867    }
 868
 869    pub fn text_anchor_for_position<'a, T: ToOffset>(
 870        &'a self,
 871        position: T,
 872        cx: &AppContext,
 873    ) -> (ModelHandle<Buffer>, language::Anchor) {
 874        let snapshot = self.read(cx);
 875        let anchor = snapshot.anchor_before(position);
 876        (
 877            self.buffers.borrow()[&anchor.buffer_id].buffer.clone(),
 878            anchor.text_anchor,
 879        )
 880    }
 881
 882    fn on_buffer_event(
 883        &mut self,
 884        _: ModelHandle<Buffer>,
 885        event: &Event,
 886        cx: &mut ModelContext<Self>,
 887    ) {
 888        cx.emit(event.clone());
 889    }
 890
 891    pub fn format(&mut self, cx: &mut ModelContext<Self>) -> Task<Result<()>> {
 892        let mut format_tasks = Vec::new();
 893        for BufferState { buffer, .. } in self.buffers.borrow().values() {
 894            format_tasks.push(buffer.update(cx, |buffer, cx| buffer.format(cx)));
 895        }
 896
 897        cx.spawn(|_, _| async move {
 898            for format in format_tasks {
 899                format.await?;
 900            }
 901            Ok(())
 902        })
 903    }
 904
 905    pub fn save(&mut self, cx: &mut ModelContext<Self>) -> Task<Result<()>> {
 906        let mut save_tasks = Vec::new();
 907        for BufferState { buffer, .. } in self.buffers.borrow().values() {
 908            save_tasks.push(buffer.update(cx, |buffer, cx| buffer.save(cx)));
 909        }
 910
 911        cx.spawn(|_, _| async move {
 912            for save in save_tasks {
 913                save.await?;
 914            }
 915            Ok(())
 916        })
 917    }
 918
 919    pub fn is_completion_trigger<T>(&self, position: T, text: &str, cx: &AppContext) -> bool
 920    where
 921        T: ToOffset,
 922    {
 923        let mut chars = text.chars();
 924        let char = if let Some(char) = chars.next() {
 925            char
 926        } else {
 927            return false;
 928        };
 929        if chars.next().is_some() {
 930            return false;
 931        }
 932
 933        if char.is_alphanumeric() || char == '_' {
 934            return true;
 935        }
 936
 937        let snapshot = self.snapshot(cx);
 938        let anchor = snapshot.anchor_before(position);
 939        let buffer = self.buffers.borrow()[&anchor.buffer_id].buffer.clone();
 940        buffer
 941            .read(cx)
 942            .completion_triggers()
 943            .iter()
 944            .any(|string| string == text)
 945    }
 946
 947    pub fn language<'a>(&self, cx: &'a AppContext) -> Option<&'a Arc<Language>> {
 948        self.buffers
 949            .borrow()
 950            .values()
 951            .next()
 952            .and_then(|state| state.buffer.read(cx).language())
 953    }
 954
 955    pub fn file<'a>(&self, cx: &'a AppContext) -> Option<&'a dyn File> {
 956        self.as_singleton()?.read(cx).file()
 957    }
 958
 959    pub fn title(&self, cx: &AppContext) -> String {
 960        if let Some(title) = self.title.clone() {
 961            title
 962        } else if let Some(file) = self.file(cx) {
 963            file.file_name(cx).to_string_lossy().into()
 964        } else {
 965            "untitled".into()
 966        }
 967    }
 968
 969    #[cfg(test)]
 970    pub fn is_parsing(&self, cx: &AppContext) -> bool {
 971        self.as_singleton().unwrap().read(cx).is_parsing()
 972    }
 973
 974    fn sync(&self, cx: &AppContext) {
 975        let mut snapshot = self.snapshot.borrow_mut();
 976        let mut excerpts_to_edit = Vec::new();
 977        let mut reparsed = false;
 978        let mut diagnostics_updated = false;
 979        let mut is_dirty = false;
 980        let mut has_conflict = false;
 981        let mut buffers = self.buffers.borrow_mut();
 982        for buffer_state in buffers.values_mut() {
 983            let buffer = buffer_state.buffer.read(cx);
 984            let version = buffer.version();
 985            let parse_count = buffer.parse_count();
 986            let selections_update_count = buffer.selections_update_count();
 987            let diagnostics_update_count = buffer.diagnostics_update_count();
 988            let file_update_count = buffer.file_update_count();
 989
 990            let buffer_edited = version.changed_since(&buffer_state.last_version);
 991            let buffer_reparsed = parse_count > buffer_state.last_parse_count;
 992            let buffer_selections_updated =
 993                selections_update_count > buffer_state.last_selections_update_count;
 994            let buffer_diagnostics_updated =
 995                diagnostics_update_count > buffer_state.last_diagnostics_update_count;
 996            let buffer_file_updated = file_update_count > buffer_state.last_file_update_count;
 997            if buffer_edited
 998                || buffer_reparsed
 999                || buffer_selections_updated
1000                || buffer_diagnostics_updated
1001                || buffer_file_updated
1002            {
1003                buffer_state.last_version = version;
1004                buffer_state.last_parse_count = parse_count;
1005                buffer_state.last_selections_update_count = selections_update_count;
1006                buffer_state.last_diagnostics_update_count = diagnostics_update_count;
1007                buffer_state.last_file_update_count = file_update_count;
1008                excerpts_to_edit.extend(
1009                    buffer_state
1010                        .excerpts
1011                        .iter()
1012                        .map(|excerpt_id| (excerpt_id, buffer_state.buffer.clone(), buffer_edited)),
1013                );
1014            }
1015
1016            reparsed |= buffer_reparsed;
1017            diagnostics_updated |= buffer_diagnostics_updated;
1018            is_dirty |= buffer.is_dirty();
1019            has_conflict |= buffer.has_conflict();
1020        }
1021        if reparsed {
1022            snapshot.parse_count += 1;
1023        }
1024        if diagnostics_updated {
1025            snapshot.diagnostics_update_count += 1;
1026        }
1027        snapshot.is_dirty = is_dirty;
1028        snapshot.has_conflict = has_conflict;
1029
1030        excerpts_to_edit.sort_unstable_by_key(|(excerpt_id, _, _)| *excerpt_id);
1031
1032        let mut edits = Vec::new();
1033        let mut new_excerpts = SumTree::new();
1034        let mut cursor = snapshot.excerpts.cursor::<(Option<&ExcerptId>, usize)>();
1035
1036        for (id, buffer, buffer_edited) in excerpts_to_edit {
1037            new_excerpts.push_tree(cursor.slice(&Some(id), Bias::Left, &()), &());
1038            let old_excerpt = cursor.item().unwrap();
1039            let buffer_id = buffer.id();
1040            let buffer = buffer.read(cx);
1041
1042            let mut new_excerpt;
1043            if buffer_edited {
1044                edits.extend(
1045                    buffer
1046                        .edits_since_in_range::<usize>(
1047                            old_excerpt.buffer.version(),
1048                            old_excerpt.range.clone(),
1049                        )
1050                        .map(|mut edit| {
1051                            let excerpt_old_start = cursor.start().1;
1052                            let excerpt_new_start = new_excerpts.summary().text.bytes;
1053                            edit.old.start += excerpt_old_start;
1054                            edit.old.end += excerpt_old_start;
1055                            edit.new.start += excerpt_new_start;
1056                            edit.new.end += excerpt_new_start;
1057                            edit
1058                        }),
1059                );
1060
1061                new_excerpt = Excerpt::new(
1062                    id.clone(),
1063                    buffer_id,
1064                    buffer.snapshot(),
1065                    old_excerpt.range.clone(),
1066                    old_excerpt.has_trailing_newline,
1067                );
1068            } else {
1069                new_excerpt = old_excerpt.clone();
1070                new_excerpt.buffer = buffer.snapshot();
1071            }
1072
1073            new_excerpts.push(new_excerpt, &());
1074            cursor.next(&());
1075        }
1076        new_excerpts.push_tree(cursor.suffix(&()), &());
1077
1078        drop(cursor);
1079        snapshot.excerpts = new_excerpts;
1080
1081        self.subscriptions.publish(edits);
1082    }
1083}
1084
1085#[cfg(any(test, feature = "test-support"))]
1086impl MultiBuffer {
1087    pub fn randomly_edit(
1088        &mut self,
1089        rng: &mut impl rand::Rng,
1090        count: usize,
1091        cx: &mut ModelContext<Self>,
1092    ) {
1093        use text::RandomCharIter;
1094
1095        let snapshot = self.read(cx);
1096        let mut old_ranges: Vec<Range<usize>> = Vec::new();
1097        for _ in 0..count {
1098            let last_end = old_ranges.last().map_or(0, |last_range| last_range.end + 1);
1099            if last_end > snapshot.len() {
1100                break;
1101            }
1102            let end_ix = snapshot.clip_offset(rng.gen_range(0..=last_end), Bias::Right);
1103            let start_ix = snapshot.clip_offset(rng.gen_range(0..=end_ix), Bias::Left);
1104            old_ranges.push(start_ix..end_ix);
1105        }
1106        let new_text_len = rng.gen_range(0..10);
1107        let new_text: String = RandomCharIter::new(&mut *rng).take(new_text_len).collect();
1108        log::info!("mutating multi-buffer at {:?}: {:?}", old_ranges, new_text);
1109        drop(snapshot);
1110
1111        self.edit(old_ranges.iter().cloned(), new_text.as_str(), cx);
1112    }
1113
1114    pub fn randomly_edit_excerpts(
1115        &mut self,
1116        rng: &mut impl rand::Rng,
1117        mutation_count: usize,
1118        cx: &mut ModelContext<Self>,
1119    ) {
1120        use rand::prelude::*;
1121        use std::env;
1122        use text::RandomCharIter;
1123
1124        let max_excerpts = env::var("MAX_EXCERPTS")
1125            .map(|i| i.parse().expect("invalid `MAX_EXCERPTS` variable"))
1126            .unwrap_or(5);
1127
1128        let mut buffers = Vec::new();
1129        for _ in 0..mutation_count {
1130            let excerpt_ids = self
1131                .buffers
1132                .borrow()
1133                .values()
1134                .flat_map(|b| &b.excerpts)
1135                .cloned()
1136                .collect::<Vec<_>>();
1137            if excerpt_ids.len() == 0 || (rng.gen() && excerpt_ids.len() < max_excerpts) {
1138                let buffer_handle = if rng.gen() || self.buffers.borrow().is_empty() {
1139                    let text = RandomCharIter::new(&mut *rng).take(10).collect::<String>();
1140                    buffers.push(cx.add_model(|cx| Buffer::new(0, text, cx)));
1141                    let buffer = buffers.last().unwrap();
1142                    log::info!(
1143                        "Creating new buffer {} with text: {:?}",
1144                        buffer.id(),
1145                        buffer.read(cx).text()
1146                    );
1147                    buffers.last().unwrap().clone()
1148                } else {
1149                    self.buffers
1150                        .borrow()
1151                        .values()
1152                        .choose(rng)
1153                        .unwrap()
1154                        .buffer
1155                        .clone()
1156                };
1157
1158                let buffer = buffer_handle.read(cx);
1159                let end_ix = buffer.clip_offset(rng.gen_range(0..=buffer.len()), Bias::Right);
1160                let start_ix = buffer.clip_offset(rng.gen_range(0..=end_ix), Bias::Left);
1161                log::info!(
1162                    "Inserting excerpt from buffer {} and range {:?}: {:?}",
1163                    buffer_handle.id(),
1164                    start_ix..end_ix,
1165                    &buffer.text()[start_ix..end_ix]
1166                );
1167
1168                let excerpt_id = self.push_excerpts(buffer_handle.clone(), [start_ix..end_ix], cx);
1169                log::info!("Inserted with id: {:?}", excerpt_id);
1170            } else {
1171                let remove_count = rng.gen_range(1..=excerpt_ids.len());
1172                let mut excerpts_to_remove = excerpt_ids
1173                    .choose_multiple(rng, remove_count)
1174                    .cloned()
1175                    .collect::<Vec<_>>();
1176                excerpts_to_remove.sort();
1177                log::info!("Removing excerpts {:?}", excerpts_to_remove);
1178                self.remove_excerpts(&excerpts_to_remove, cx);
1179            }
1180        }
1181    }
1182
1183    pub fn randomly_mutate(
1184        &mut self,
1185        rng: &mut impl rand::Rng,
1186        mutation_count: usize,
1187        cx: &mut ModelContext<Self>,
1188    ) {
1189        if rng.gen_bool(0.7) || self.singleton {
1190            self.randomly_edit(rng, mutation_count, cx);
1191        } else {
1192            self.randomly_edit_excerpts(rng, mutation_count, cx);
1193        }
1194    }
1195}
1196
1197impl Entity for MultiBuffer {
1198    type Event = language::Event;
1199}
1200
1201impl MultiBufferSnapshot {
1202    pub fn text(&self) -> String {
1203        self.chunks(0..self.len(), false)
1204            .map(|chunk| chunk.text)
1205            .collect()
1206    }
1207
1208    pub fn reversed_chars_at<'a, T: ToOffset>(
1209        &'a self,
1210        position: T,
1211    ) -> impl Iterator<Item = char> + 'a {
1212        let mut offset = position.to_offset(self);
1213        let mut cursor = self.excerpts.cursor::<usize>();
1214        cursor.seek(&offset, Bias::Left, &());
1215        let mut excerpt_chunks = cursor.item().map(|excerpt| {
1216            let end_before_footer = cursor.start() + excerpt.text_summary.bytes;
1217            let start = excerpt.range.start.to_offset(&excerpt.buffer);
1218            let end = start + (cmp::min(offset, end_before_footer) - cursor.start());
1219            excerpt.buffer.reversed_chunks_in_range(start..end)
1220        });
1221        iter::from_fn(move || {
1222            if offset == *cursor.start() {
1223                cursor.prev(&());
1224                let excerpt = cursor.item()?;
1225                excerpt_chunks = Some(
1226                    excerpt
1227                        .buffer
1228                        .reversed_chunks_in_range(excerpt.range.clone()),
1229                );
1230            }
1231
1232            let excerpt = cursor.item().unwrap();
1233            if offset == cursor.end(&()) && excerpt.has_trailing_newline {
1234                offset -= 1;
1235                Some("\n")
1236            } else {
1237                let chunk = excerpt_chunks.as_mut().unwrap().next().unwrap();
1238                offset -= chunk.len();
1239                Some(chunk)
1240            }
1241        })
1242        .flat_map(|c| c.chars().rev())
1243    }
1244
1245    pub fn chars_at<'a, T: ToOffset>(&'a self, position: T) -> impl Iterator<Item = char> + 'a {
1246        let offset = position.to_offset(self);
1247        self.text_for_range(offset..self.len())
1248            .flat_map(|chunk| chunk.chars())
1249    }
1250
1251    pub fn text_for_range<'a, T: ToOffset>(
1252        &'a self,
1253        range: Range<T>,
1254    ) -> impl Iterator<Item = &'a str> {
1255        self.chunks(range, false).map(|chunk| chunk.text)
1256    }
1257
1258    pub fn is_line_blank(&self, row: u32) -> bool {
1259        self.text_for_range(Point::new(row, 0)..Point::new(row, self.line_len(row)))
1260            .all(|chunk| chunk.matches(|c: char| !c.is_whitespace()).next().is_none())
1261    }
1262
1263    pub fn contains_str_at<T>(&self, position: T, needle: &str) -> bool
1264    where
1265        T: ToOffset,
1266    {
1267        let position = position.to_offset(self);
1268        position == self.clip_offset(position, Bias::Left)
1269            && self
1270                .bytes_in_range(position..self.len())
1271                .flatten()
1272                .copied()
1273                .take(needle.len())
1274                .eq(needle.bytes())
1275    }
1276
1277    pub fn surrounding_word<T: ToOffset>(&self, start: T) -> (Range<usize>, Option<CharKind>) {
1278        let mut start = start.to_offset(self);
1279        let mut end = start;
1280        let mut next_chars = self.chars_at(start).peekable();
1281        let mut prev_chars = self.reversed_chars_at(start).peekable();
1282        let word_kind = cmp::max(
1283            prev_chars.peek().copied().map(char_kind),
1284            next_chars.peek().copied().map(char_kind),
1285        );
1286
1287        for ch in prev_chars {
1288            if Some(char_kind(ch)) == word_kind {
1289                start -= ch.len_utf8();
1290            } else {
1291                break;
1292            }
1293        }
1294
1295        for ch in next_chars {
1296            if Some(char_kind(ch)) == word_kind {
1297                end += ch.len_utf8();
1298            } else {
1299                break;
1300            }
1301        }
1302
1303        (start..end, word_kind)
1304    }
1305
1306    fn as_singleton(&self) -> Option<&Excerpt> {
1307        if self.singleton {
1308            self.excerpts.iter().next()
1309        } else {
1310            None
1311        }
1312    }
1313
1314    pub fn len(&self) -> usize {
1315        self.excerpts.summary().text.bytes
1316    }
1317
1318    pub fn max_buffer_row(&self) -> u32 {
1319        self.excerpts.summary().max_buffer_row
1320    }
1321
1322    pub fn clip_offset(&self, offset: usize, bias: Bias) -> usize {
1323        if let Some(excerpt) = self.as_singleton() {
1324            return excerpt.buffer.clip_offset(offset, bias);
1325        }
1326
1327        let mut cursor = self.excerpts.cursor::<usize>();
1328        cursor.seek(&offset, Bias::Right, &());
1329        let overshoot = if let Some(excerpt) = cursor.item() {
1330            let excerpt_start = excerpt.range.start.to_offset(&excerpt.buffer);
1331            let buffer_offset = excerpt
1332                .buffer
1333                .clip_offset(excerpt_start + (offset - cursor.start()), bias);
1334            buffer_offset.saturating_sub(excerpt_start)
1335        } else {
1336            0
1337        };
1338        cursor.start() + overshoot
1339    }
1340
1341    pub fn clip_point(&self, point: Point, bias: Bias) -> Point {
1342        if let Some(excerpt) = self.as_singleton() {
1343            return excerpt.buffer.clip_point(point, bias);
1344        }
1345
1346        let mut cursor = self.excerpts.cursor::<Point>();
1347        cursor.seek(&point, Bias::Right, &());
1348        let overshoot = if let Some(excerpt) = cursor.item() {
1349            let excerpt_start = excerpt.range.start.to_point(&excerpt.buffer);
1350            let buffer_point = excerpt
1351                .buffer
1352                .clip_point(excerpt_start + (point - cursor.start()), bias);
1353            buffer_point.saturating_sub(excerpt_start)
1354        } else {
1355            Point::zero()
1356        };
1357        *cursor.start() + overshoot
1358    }
1359
1360    pub fn clip_point_utf16(&self, point: PointUtf16, bias: Bias) -> PointUtf16 {
1361        if let Some(excerpt) = self.as_singleton() {
1362            return excerpt.buffer.clip_point_utf16(point, bias);
1363        }
1364
1365        let mut cursor = self.excerpts.cursor::<PointUtf16>();
1366        cursor.seek(&point, Bias::Right, &());
1367        let overshoot = if let Some(excerpt) = cursor.item() {
1368            let excerpt_start = excerpt
1369                .buffer
1370                .offset_to_point_utf16(excerpt.range.start.to_offset(&excerpt.buffer));
1371            let buffer_point = excerpt
1372                .buffer
1373                .clip_point_utf16(excerpt_start + (point - cursor.start()), bias);
1374            buffer_point.saturating_sub(excerpt_start)
1375        } else {
1376            PointUtf16::zero()
1377        };
1378        *cursor.start() + overshoot
1379    }
1380
1381    pub fn bytes_in_range<'a, T: ToOffset>(&'a self, range: Range<T>) -> MultiBufferBytes<'a> {
1382        let range = range.start.to_offset(self)..range.end.to_offset(self);
1383        let mut excerpts = self.excerpts.cursor::<usize>();
1384        excerpts.seek(&range.start, Bias::Right, &());
1385
1386        let mut chunk = &[][..];
1387        let excerpt_bytes = if let Some(excerpt) = excerpts.item() {
1388            let mut excerpt_bytes = excerpt
1389                .bytes_in_range(range.start - excerpts.start()..range.end - excerpts.start());
1390            chunk = excerpt_bytes.next().unwrap_or(&[][..]);
1391            Some(excerpt_bytes)
1392        } else {
1393            None
1394        };
1395
1396        MultiBufferBytes {
1397            range,
1398            excerpts,
1399            excerpt_bytes,
1400            chunk,
1401        }
1402    }
1403
1404    pub fn buffer_rows<'a>(&'a self, start_row: u32) -> MultiBufferRows<'a> {
1405        let mut result = MultiBufferRows {
1406            buffer_row_range: 0..0,
1407            excerpts: self.excerpts.cursor(),
1408        };
1409        result.seek(start_row);
1410        result
1411    }
1412
1413    pub fn chunks<'a, T: ToOffset>(
1414        &'a self,
1415        range: Range<T>,
1416        language_aware: bool,
1417    ) -> MultiBufferChunks<'a> {
1418        let range = range.start.to_offset(self)..range.end.to_offset(self);
1419        let mut chunks = MultiBufferChunks {
1420            range: range.clone(),
1421            excerpts: self.excerpts.cursor(),
1422            excerpt_chunks: None,
1423            language_aware,
1424        };
1425        chunks.seek(range.start);
1426        chunks
1427    }
1428
1429    pub fn offset_to_point(&self, offset: usize) -> Point {
1430        if let Some(excerpt) = self.as_singleton() {
1431            return excerpt.buffer.offset_to_point(offset);
1432        }
1433
1434        let mut cursor = self.excerpts.cursor::<(usize, Point)>();
1435        cursor.seek(&offset, Bias::Right, &());
1436        if let Some(excerpt) = cursor.item() {
1437            let (start_offset, start_point) = cursor.start();
1438            let overshoot = offset - start_offset;
1439            let excerpt_start_offset = excerpt.range.start.to_offset(&excerpt.buffer);
1440            let excerpt_start_point = excerpt.range.start.to_point(&excerpt.buffer);
1441            let buffer_point = excerpt
1442                .buffer
1443                .offset_to_point(excerpt_start_offset + overshoot);
1444            *start_point + (buffer_point - excerpt_start_point)
1445        } else {
1446            self.excerpts.summary().text.lines
1447        }
1448    }
1449
1450    pub fn offset_to_point_utf16(&self, offset: usize) -> PointUtf16 {
1451        if let Some(excerpt) = self.as_singleton() {
1452            return excerpt.buffer.offset_to_point_utf16(offset);
1453        }
1454
1455        let mut cursor = self.excerpts.cursor::<(usize, PointUtf16)>();
1456        cursor.seek(&offset, Bias::Right, &());
1457        if let Some(excerpt) = cursor.item() {
1458            let (start_offset, start_point) = cursor.start();
1459            let overshoot = offset - start_offset;
1460            let excerpt_start_offset = excerpt.range.start.to_offset(&excerpt.buffer);
1461            let excerpt_start_point = excerpt.range.start.to_point_utf16(&excerpt.buffer);
1462            let buffer_point = excerpt
1463                .buffer
1464                .offset_to_point_utf16(excerpt_start_offset + overshoot);
1465            *start_point + (buffer_point - excerpt_start_point)
1466        } else {
1467            self.excerpts.summary().text.lines_utf16
1468        }
1469    }
1470
1471    pub fn point_to_point_utf16(&self, point: Point) -> PointUtf16 {
1472        if let Some(excerpt) = self.as_singleton() {
1473            return excerpt.buffer.point_to_point_utf16(point);
1474        }
1475
1476        let mut cursor = self.excerpts.cursor::<(Point, PointUtf16)>();
1477        cursor.seek(&point, Bias::Right, &());
1478        if let Some(excerpt) = cursor.item() {
1479            let (start_offset, start_point) = cursor.start();
1480            let overshoot = point - start_offset;
1481            let excerpt_start_point = excerpt.range.start.to_point(&excerpt.buffer);
1482            let excerpt_start_point_utf16 = excerpt.range.start.to_point_utf16(&excerpt.buffer);
1483            let buffer_point = excerpt
1484                .buffer
1485                .point_to_point_utf16(excerpt_start_point + overshoot);
1486            *start_point + (buffer_point - excerpt_start_point_utf16)
1487        } else {
1488            self.excerpts.summary().text.lines_utf16
1489        }
1490    }
1491
1492    pub fn point_to_offset(&self, point: Point) -> usize {
1493        if let Some(excerpt) = self.as_singleton() {
1494            return excerpt.buffer.point_to_offset(point);
1495        }
1496
1497        let mut cursor = self.excerpts.cursor::<(Point, usize)>();
1498        cursor.seek(&point, Bias::Right, &());
1499        if let Some(excerpt) = cursor.item() {
1500            let (start_point, start_offset) = cursor.start();
1501            let overshoot = point - start_point;
1502            let excerpt_start_offset = excerpt.range.start.to_offset(&excerpt.buffer);
1503            let excerpt_start_point = excerpt.range.start.to_point(&excerpt.buffer);
1504            let buffer_offset = excerpt
1505                .buffer
1506                .point_to_offset(excerpt_start_point + overshoot);
1507            *start_offset + buffer_offset - excerpt_start_offset
1508        } else {
1509            self.excerpts.summary().text.bytes
1510        }
1511    }
1512
1513    pub fn point_utf16_to_offset(&self, point: PointUtf16) -> usize {
1514        if let Some(excerpt) = self.as_singleton() {
1515            return excerpt.buffer.point_utf16_to_offset(point);
1516        }
1517
1518        let mut cursor = self.excerpts.cursor::<(PointUtf16, usize)>();
1519        cursor.seek(&point, Bias::Right, &());
1520        if let Some(excerpt) = cursor.item() {
1521            let (start_point, start_offset) = cursor.start();
1522            let overshoot = point - start_point;
1523            let excerpt_start_offset = excerpt.range.start.to_offset(&excerpt.buffer);
1524            let excerpt_start_point = excerpt
1525                .buffer
1526                .offset_to_point_utf16(excerpt.range.start.to_offset(&excerpt.buffer));
1527            let buffer_offset = excerpt
1528                .buffer
1529                .point_utf16_to_offset(excerpt_start_point + overshoot);
1530            *start_offset + (buffer_offset - excerpt_start_offset)
1531        } else {
1532            self.excerpts.summary().text.bytes
1533        }
1534    }
1535
1536    pub fn indent_column_for_line(&self, row: u32) -> u32 {
1537        if let Some((buffer, range)) = self.buffer_line_for_row(row) {
1538            buffer
1539                .indent_column_for_line(range.start.row)
1540                .min(range.end.column)
1541                .saturating_sub(range.start.column)
1542        } else {
1543            0
1544        }
1545    }
1546
1547    pub fn line_len(&self, row: u32) -> u32 {
1548        if let Some((_, range)) = self.buffer_line_for_row(row) {
1549            range.end.column - range.start.column
1550        } else {
1551            0
1552        }
1553    }
1554
1555    fn buffer_line_for_row(&self, row: u32) -> Option<(&BufferSnapshot, Range<Point>)> {
1556        let mut cursor = self.excerpts.cursor::<Point>();
1557        cursor.seek(&Point::new(row, 0), Bias::Right, &());
1558        if let Some(excerpt) = cursor.item() {
1559            let overshoot = row - cursor.start().row;
1560            let excerpt_start = excerpt.range.start.to_point(&excerpt.buffer);
1561            let excerpt_end = excerpt.range.end.to_point(&excerpt.buffer);
1562            let buffer_row = excerpt_start.row + overshoot;
1563            let line_start = Point::new(buffer_row, 0);
1564            let line_end = Point::new(buffer_row, excerpt.buffer.line_len(buffer_row));
1565            return Some((
1566                &excerpt.buffer,
1567                line_start.max(excerpt_start)..line_end.min(excerpt_end),
1568            ));
1569        }
1570        None
1571    }
1572
1573    pub fn max_point(&self) -> Point {
1574        self.text_summary().lines
1575    }
1576
1577    pub fn text_summary(&self) -> TextSummary {
1578        self.excerpts.summary().text
1579    }
1580
1581    pub fn text_summary_for_range<'a, D, O>(&'a self, range: Range<O>) -> D
1582    where
1583        D: TextDimension,
1584        O: ToOffset,
1585    {
1586        let mut summary = D::default();
1587        let mut range = range.start.to_offset(self)..range.end.to_offset(self);
1588        let mut cursor = self.excerpts.cursor::<usize>();
1589        cursor.seek(&range.start, Bias::Right, &());
1590        if let Some(excerpt) = cursor.item() {
1591            let mut end_before_newline = cursor.end(&());
1592            if excerpt.has_trailing_newline {
1593                end_before_newline -= 1;
1594            }
1595
1596            let excerpt_start = excerpt.range.start.to_offset(&excerpt.buffer);
1597            let start_in_excerpt = excerpt_start + (range.start - cursor.start());
1598            let end_in_excerpt =
1599                excerpt_start + (cmp::min(end_before_newline, range.end) - cursor.start());
1600            summary.add_assign(
1601                &excerpt
1602                    .buffer
1603                    .text_summary_for_range(start_in_excerpt..end_in_excerpt),
1604            );
1605
1606            if range.end > end_before_newline {
1607                summary.add_assign(&D::from_text_summary(&TextSummary {
1608                    bytes: 1,
1609                    lines: Point::new(1 as u32, 0),
1610                    lines_utf16: PointUtf16::new(1 as u32, 0),
1611                    first_line_chars: 0,
1612                    last_line_chars: 0,
1613                    longest_row: 0,
1614                    longest_row_chars: 0,
1615                }));
1616            }
1617
1618            cursor.next(&());
1619        }
1620
1621        if range.end > *cursor.start() {
1622            summary.add_assign(&D::from_text_summary(&cursor.summary::<_, TextSummary>(
1623                &range.end,
1624                Bias::Right,
1625                &(),
1626            )));
1627            if let Some(excerpt) = cursor.item() {
1628                range.end = cmp::max(*cursor.start(), range.end);
1629
1630                let excerpt_start = excerpt.range.start.to_offset(&excerpt.buffer);
1631                let end_in_excerpt = excerpt_start + (range.end - cursor.start());
1632                summary.add_assign(
1633                    &excerpt
1634                        .buffer
1635                        .text_summary_for_range(excerpt_start..end_in_excerpt),
1636                );
1637            }
1638        }
1639
1640        summary
1641    }
1642
1643    pub fn summary_for_anchor<D>(&self, anchor: &Anchor) -> D
1644    where
1645        D: TextDimension + Ord + Sub<D, Output = D>,
1646    {
1647        let mut cursor = self.excerpts.cursor::<ExcerptSummary>();
1648        cursor.seek(&Some(&anchor.excerpt_id), Bias::Left, &());
1649        if cursor.item().is_none() {
1650            cursor.next(&());
1651        }
1652
1653        let mut position = D::from_text_summary(&cursor.start().text);
1654        if let Some(excerpt) = cursor.item() {
1655            if excerpt.id == anchor.excerpt_id && excerpt.buffer_id == anchor.buffer_id {
1656                let excerpt_buffer_start = excerpt.range.start.summary::<D>(&excerpt.buffer);
1657                let excerpt_buffer_end = excerpt.range.end.summary::<D>(&excerpt.buffer);
1658                let buffer_position = cmp::min(
1659                    excerpt_buffer_end,
1660                    anchor.text_anchor.summary::<D>(&excerpt.buffer),
1661                );
1662                if buffer_position > excerpt_buffer_start {
1663                    position.add_assign(&(buffer_position - excerpt_buffer_start));
1664                }
1665            }
1666        }
1667        position
1668    }
1669
1670    pub fn summaries_for_anchors<'a, D, I>(&'a self, anchors: I) -> Vec<D>
1671    where
1672        D: TextDimension + Ord + Sub<D, Output = D>,
1673        I: 'a + IntoIterator<Item = &'a Anchor>,
1674    {
1675        if let Some(excerpt) = self.as_singleton() {
1676            return excerpt
1677                .buffer
1678                .summaries_for_anchors(anchors.into_iter().map(|a| &a.text_anchor))
1679                .collect();
1680        }
1681
1682        let mut anchors = anchors.into_iter().peekable();
1683        let mut cursor = self.excerpts.cursor::<ExcerptSummary>();
1684        let mut summaries = Vec::new();
1685        while let Some(anchor) = anchors.peek() {
1686            let excerpt_id = &anchor.excerpt_id;
1687            let buffer_id = anchor.buffer_id;
1688            let excerpt_anchors = iter::from_fn(|| {
1689                let anchor = anchors.peek()?;
1690                if anchor.excerpt_id == *excerpt_id && anchor.buffer_id == buffer_id {
1691                    Some(&anchors.next().unwrap().text_anchor)
1692                } else {
1693                    None
1694                }
1695            });
1696
1697            cursor.seek_forward(&Some(excerpt_id), Bias::Left, &());
1698            if cursor.item().is_none() {
1699                cursor.next(&());
1700            }
1701
1702            let position = D::from_text_summary(&cursor.start().text);
1703            if let Some(excerpt) = cursor.item() {
1704                if excerpt.id == *excerpt_id && excerpt.buffer_id == buffer_id {
1705                    let excerpt_buffer_start = excerpt.range.start.summary::<D>(&excerpt.buffer);
1706                    let excerpt_buffer_end = excerpt.range.end.summary::<D>(&excerpt.buffer);
1707                    summaries.extend(
1708                        excerpt
1709                            .buffer
1710                            .summaries_for_anchors::<D, _>(excerpt_anchors)
1711                            .map(move |summary| {
1712                                let summary = cmp::min(excerpt_buffer_end.clone(), summary);
1713                                let mut position = position.clone();
1714                                let excerpt_buffer_start = excerpt_buffer_start.clone();
1715                                if summary > excerpt_buffer_start {
1716                                    position.add_assign(&(summary - excerpt_buffer_start));
1717                                }
1718                                position
1719                            }),
1720                    );
1721                    continue;
1722                }
1723            }
1724
1725            summaries.extend(excerpt_anchors.map(|_| position.clone()));
1726        }
1727
1728        summaries
1729    }
1730
1731    pub fn refresh_anchors<'a, I>(&'a self, anchors: I) -> Vec<(usize, Anchor, bool)>
1732    where
1733        I: 'a + IntoIterator<Item = &'a Anchor>,
1734    {
1735        let mut anchors = anchors.into_iter().enumerate().peekable();
1736        let mut cursor = self.excerpts.cursor::<Option<&ExcerptId>>();
1737        let mut result = Vec::new();
1738        while let Some((_, anchor)) = anchors.peek() {
1739            let old_excerpt_id = &anchor.excerpt_id;
1740
1741            // Find the location where this anchor's excerpt should be.
1742            cursor.seek_forward(&Some(old_excerpt_id), Bias::Left, &());
1743            if cursor.item().is_none() {
1744                cursor.next(&());
1745            }
1746
1747            let next_excerpt = cursor.item();
1748            let prev_excerpt = cursor.prev_item();
1749
1750            // Process all of the anchors for this excerpt.
1751            while let Some((_, anchor)) = anchors.peek() {
1752                if anchor.excerpt_id != *old_excerpt_id {
1753                    break;
1754                }
1755                let mut kept_position = false;
1756                let (anchor_ix, anchor) = anchors.next().unwrap();
1757                let mut anchor = anchor.clone();
1758
1759                // Leave min and max anchors unchanged.
1760                if *old_excerpt_id == ExcerptId::max() || *old_excerpt_id == ExcerptId::min() {
1761                    kept_position = true;
1762                }
1763                // If the old excerpt still exists at this location, then leave
1764                // the anchor unchanged.
1765                else if next_excerpt.map_or(false, |excerpt| {
1766                    excerpt.id == *old_excerpt_id && excerpt.contains(&anchor)
1767                }) {
1768                    kept_position = true;
1769                }
1770                // If the old excerpt no longer exists at this location, then attempt to
1771                // find an equivalent position for this anchor in an adjacent excerpt.
1772                else {
1773                    for excerpt in [next_excerpt, prev_excerpt].iter().filter_map(|e| *e) {
1774                        if excerpt.contains(&anchor) {
1775                            anchor.excerpt_id = excerpt.id.clone();
1776                            kept_position = true;
1777                            break;
1778                        }
1779                    }
1780                }
1781                // If there's no adjacent excerpt that contains the anchor's position,
1782                // then report that the anchor has lost its position.
1783                if !kept_position {
1784                    anchor = if let Some(excerpt) = next_excerpt {
1785                        let mut text_anchor = excerpt
1786                            .range
1787                            .start
1788                            .bias(anchor.text_anchor.bias, &excerpt.buffer);
1789                        if text_anchor
1790                            .cmp(&excerpt.range.end, &excerpt.buffer)
1791                            .unwrap()
1792                            .is_gt()
1793                        {
1794                            text_anchor = excerpt.range.end.clone();
1795                        }
1796                        Anchor {
1797                            buffer_id: excerpt.buffer_id,
1798                            excerpt_id: excerpt.id.clone(),
1799                            text_anchor,
1800                        }
1801                    } else if let Some(excerpt) = prev_excerpt {
1802                        let mut text_anchor = excerpt
1803                            .range
1804                            .end
1805                            .bias(anchor.text_anchor.bias, &excerpt.buffer);
1806                        if text_anchor
1807                            .cmp(&excerpt.range.start, &excerpt.buffer)
1808                            .unwrap()
1809                            .is_lt()
1810                        {
1811                            text_anchor = excerpt.range.start.clone();
1812                        }
1813                        Anchor {
1814                            buffer_id: excerpt.buffer_id,
1815                            excerpt_id: excerpt.id.clone(),
1816                            text_anchor,
1817                        }
1818                    } else if anchor.text_anchor.bias == Bias::Left {
1819                        Anchor::min()
1820                    } else {
1821                        Anchor::max()
1822                    };
1823                }
1824
1825                result.push((anchor_ix, anchor, kept_position));
1826            }
1827        }
1828        result.sort_unstable_by(|a, b| a.1.cmp(&b.1, self).unwrap());
1829        result
1830    }
1831
1832    pub fn anchor_before<T: ToOffset>(&self, position: T) -> Anchor {
1833        self.anchor_at(position, Bias::Left)
1834    }
1835
1836    pub fn anchor_after<T: ToOffset>(&self, position: T) -> Anchor {
1837        self.anchor_at(position, Bias::Right)
1838    }
1839
1840    pub fn anchor_at<T: ToOffset>(&self, position: T, mut bias: Bias) -> Anchor {
1841        let offset = position.to_offset(self);
1842        if let Some(excerpt) = self.as_singleton() {
1843            return Anchor {
1844                buffer_id: excerpt.buffer_id,
1845                excerpt_id: excerpt.id.clone(),
1846                text_anchor: excerpt.buffer.anchor_at(offset, bias),
1847            };
1848        }
1849
1850        let mut cursor = self.excerpts.cursor::<(usize, Option<&ExcerptId>)>();
1851        cursor.seek(&offset, Bias::Right, &());
1852        if cursor.item().is_none() && offset == cursor.start().0 && bias == Bias::Left {
1853            cursor.prev(&());
1854        }
1855        if let Some(excerpt) = cursor.item() {
1856            let mut overshoot = offset.saturating_sub(cursor.start().0);
1857            if excerpt.has_trailing_newline && offset == cursor.end(&()).0 {
1858                overshoot -= 1;
1859                bias = Bias::Right;
1860            }
1861
1862            let buffer_start = excerpt.range.start.to_offset(&excerpt.buffer);
1863            let text_anchor =
1864                excerpt.clip_anchor(excerpt.buffer.anchor_at(buffer_start + overshoot, bias));
1865            Anchor {
1866                buffer_id: excerpt.buffer_id,
1867                excerpt_id: excerpt.id.clone(),
1868                text_anchor,
1869            }
1870        } else if offset == 0 && bias == Bias::Left {
1871            Anchor::min()
1872        } else {
1873            Anchor::max()
1874        }
1875    }
1876
1877    pub fn anchor_in_excerpt(&self, excerpt_id: ExcerptId, text_anchor: text::Anchor) -> Anchor {
1878        let mut cursor = self.excerpts.cursor::<Option<&ExcerptId>>();
1879        cursor.seek(&Some(&excerpt_id), Bias::Left, &());
1880        if let Some(excerpt) = cursor.item() {
1881            if excerpt.id == excerpt_id {
1882                let text_anchor = excerpt.clip_anchor(text_anchor);
1883                drop(cursor);
1884                return Anchor {
1885                    buffer_id: excerpt.buffer_id,
1886                    excerpt_id,
1887                    text_anchor,
1888                };
1889            }
1890        }
1891        panic!("excerpt not found");
1892    }
1893
1894    pub fn can_resolve(&self, anchor: &Anchor) -> bool {
1895        if anchor.excerpt_id == ExcerptId::min() || anchor.excerpt_id == ExcerptId::max() {
1896            true
1897        } else if let Some((buffer_id, buffer_snapshot)) =
1898            self.buffer_snapshot_for_excerpt(&anchor.excerpt_id)
1899        {
1900            anchor.buffer_id == buffer_id && buffer_snapshot.can_resolve(&anchor.text_anchor)
1901        } else {
1902            false
1903        }
1904    }
1905
1906    pub fn excerpt_boundaries_in_range<'a, R, T>(
1907        &'a self,
1908        range: R,
1909    ) -> impl Iterator<Item = ExcerptBoundary> + 'a
1910    where
1911        R: RangeBounds<T>,
1912        T: ToOffset,
1913    {
1914        let start_offset;
1915        let start = match range.start_bound() {
1916            Bound::Included(start) => {
1917                start_offset = start.to_offset(self);
1918                Bound::Included(start_offset)
1919            }
1920            Bound::Excluded(start) => {
1921                start_offset = start.to_offset(self);
1922                Bound::Excluded(start_offset)
1923            }
1924            Bound::Unbounded => {
1925                start_offset = 0;
1926                Bound::Unbounded
1927            }
1928        };
1929        let end = match range.end_bound() {
1930            Bound::Included(end) => Bound::Included(end.to_offset(self)),
1931            Bound::Excluded(end) => Bound::Excluded(end.to_offset(self)),
1932            Bound::Unbounded => Bound::Unbounded,
1933        };
1934        let bounds = (start, end);
1935
1936        let mut cursor = self.excerpts.cursor::<(usize, Point)>();
1937        cursor.seek(&start_offset, Bias::Right, &());
1938        if cursor.item().is_none() {
1939            cursor.prev(&());
1940        }
1941        if !bounds.contains(&cursor.start().0) {
1942            cursor.next(&());
1943        }
1944
1945        let mut prev_buffer_id = cursor.prev_item().map(|excerpt| excerpt.buffer_id);
1946        std::iter::from_fn(move || {
1947            if self.singleton {
1948                None
1949            } else if bounds.contains(&cursor.start().0) {
1950                let excerpt = cursor.item()?;
1951                let starts_new_buffer = Some(excerpt.buffer_id) != prev_buffer_id;
1952                let boundary = ExcerptBoundary {
1953                    row: cursor.start().1.row,
1954                    buffer: excerpt.buffer.clone(),
1955                    range: excerpt.range.clone(),
1956                    starts_new_buffer,
1957                };
1958
1959                prev_buffer_id = Some(excerpt.buffer_id);
1960                cursor.next(&());
1961                Some(boundary)
1962            } else {
1963                None
1964            }
1965        })
1966    }
1967
1968    pub fn parse_count(&self) -> usize {
1969        self.parse_count
1970    }
1971
1972    pub fn enclosing_bracket_ranges<T: ToOffset>(
1973        &self,
1974        range: Range<T>,
1975    ) -> Option<(Range<usize>, Range<usize>)> {
1976        let range = range.start.to_offset(self)..range.end.to_offset(self);
1977
1978        let mut cursor = self.excerpts.cursor::<usize>();
1979        cursor.seek(&range.start, Bias::Right, &());
1980        let start_excerpt = cursor.item();
1981
1982        cursor.seek(&range.end, Bias::Right, &());
1983        let end_excerpt = cursor.item();
1984
1985        start_excerpt
1986            .zip(end_excerpt)
1987            .and_then(|(start_excerpt, end_excerpt)| {
1988                if start_excerpt.id != end_excerpt.id {
1989                    return None;
1990                }
1991
1992                let excerpt_buffer_start =
1993                    start_excerpt.range.start.to_offset(&start_excerpt.buffer);
1994                let excerpt_buffer_end = excerpt_buffer_start + start_excerpt.text_summary.bytes;
1995
1996                let start_in_buffer =
1997                    excerpt_buffer_start + range.start.saturating_sub(*cursor.start());
1998                let end_in_buffer =
1999                    excerpt_buffer_start + range.end.saturating_sub(*cursor.start());
2000                let (mut start_bracket_range, mut end_bracket_range) = start_excerpt
2001                    .buffer
2002                    .enclosing_bracket_ranges(start_in_buffer..end_in_buffer)?;
2003
2004                if start_bracket_range.start >= excerpt_buffer_start
2005                    && end_bracket_range.end < excerpt_buffer_end
2006                {
2007                    start_bracket_range.start =
2008                        cursor.start() + (start_bracket_range.start - excerpt_buffer_start);
2009                    start_bracket_range.end =
2010                        cursor.start() + (start_bracket_range.end - excerpt_buffer_start);
2011                    end_bracket_range.start =
2012                        cursor.start() + (end_bracket_range.start - excerpt_buffer_start);
2013                    end_bracket_range.end =
2014                        cursor.start() + (end_bracket_range.end - excerpt_buffer_start);
2015                    Some((start_bracket_range, end_bracket_range))
2016                } else {
2017                    None
2018                }
2019            })
2020    }
2021
2022    pub fn diagnostics_update_count(&self) -> usize {
2023        self.diagnostics_update_count
2024    }
2025
2026    pub fn trailing_excerpt_update_count(&self) -> usize {
2027        self.trailing_excerpt_update_count
2028    }
2029
2030    pub fn language(&self) -> Option<&Arc<Language>> {
2031        self.excerpts
2032            .iter()
2033            .next()
2034            .and_then(|excerpt| excerpt.buffer.language())
2035    }
2036
2037    pub fn is_dirty(&self) -> bool {
2038        self.is_dirty
2039    }
2040
2041    pub fn has_conflict(&self) -> bool {
2042        self.has_conflict
2043    }
2044
2045    pub fn diagnostic_group<'a, O>(
2046        &'a self,
2047        group_id: usize,
2048    ) -> impl Iterator<Item = DiagnosticEntry<O>> + 'a
2049    where
2050        O: text::FromAnchor + 'a,
2051    {
2052        self.as_singleton()
2053            .into_iter()
2054            .flat_map(move |excerpt| excerpt.buffer.diagnostic_group(group_id))
2055    }
2056
2057    pub fn diagnostics_in_range<'a, T, O>(
2058        &'a self,
2059        range: Range<T>,
2060    ) -> impl Iterator<Item = DiagnosticEntry<O>> + 'a
2061    where
2062        T: 'a + ToOffset,
2063        O: 'a + text::FromAnchor,
2064    {
2065        self.as_singleton().into_iter().flat_map(move |excerpt| {
2066            excerpt
2067                .buffer
2068                .diagnostics_in_range(range.start.to_offset(self)..range.end.to_offset(self))
2069        })
2070    }
2071
2072    pub fn range_for_syntax_ancestor<T: ToOffset>(&self, range: Range<T>) -> Option<Range<usize>> {
2073        let range = range.start.to_offset(self)..range.end.to_offset(self);
2074
2075        let mut cursor = self.excerpts.cursor::<usize>();
2076        cursor.seek(&range.start, Bias::Right, &());
2077        let start_excerpt = cursor.item();
2078
2079        cursor.seek(&range.end, Bias::Right, &());
2080        let end_excerpt = cursor.item();
2081
2082        start_excerpt
2083            .zip(end_excerpt)
2084            .and_then(|(start_excerpt, end_excerpt)| {
2085                if start_excerpt.id != end_excerpt.id {
2086                    return None;
2087                }
2088
2089                let excerpt_buffer_start =
2090                    start_excerpt.range.start.to_offset(&start_excerpt.buffer);
2091                let excerpt_buffer_end = excerpt_buffer_start + start_excerpt.text_summary.bytes;
2092
2093                let start_in_buffer =
2094                    excerpt_buffer_start + range.start.saturating_sub(*cursor.start());
2095                let end_in_buffer =
2096                    excerpt_buffer_start + range.end.saturating_sub(*cursor.start());
2097                let mut ancestor_buffer_range = start_excerpt
2098                    .buffer
2099                    .range_for_syntax_ancestor(start_in_buffer..end_in_buffer)?;
2100                ancestor_buffer_range.start =
2101                    cmp::max(ancestor_buffer_range.start, excerpt_buffer_start);
2102                ancestor_buffer_range.end = cmp::min(ancestor_buffer_range.end, excerpt_buffer_end);
2103
2104                let start = cursor.start() + (ancestor_buffer_range.start - excerpt_buffer_start);
2105                let end = cursor.start() + (ancestor_buffer_range.end - excerpt_buffer_start);
2106                Some(start..end)
2107            })
2108    }
2109
2110    pub fn outline(&self, theme: Option<&SyntaxTheme>) -> Option<Outline<Anchor>> {
2111        let excerpt = self.as_singleton()?;
2112        let outline = excerpt.buffer.outline(theme)?;
2113        Some(Outline::new(
2114            outline
2115                .items
2116                .into_iter()
2117                .map(|item| OutlineItem {
2118                    depth: item.depth,
2119                    range: self.anchor_in_excerpt(excerpt.id.clone(), item.range.start)
2120                        ..self.anchor_in_excerpt(excerpt.id.clone(), item.range.end),
2121                    text: item.text,
2122                    highlight_ranges: item.highlight_ranges,
2123                    name_ranges: item.name_ranges,
2124                })
2125                .collect(),
2126        ))
2127    }
2128
2129    fn buffer_snapshot_for_excerpt<'a>(
2130        &'a self,
2131        excerpt_id: &'a ExcerptId,
2132    ) -> Option<(usize, &'a BufferSnapshot)> {
2133        let mut cursor = self.excerpts.cursor::<Option<&ExcerptId>>();
2134        cursor.seek(&Some(excerpt_id), Bias::Left, &());
2135        if let Some(excerpt) = cursor.item() {
2136            if excerpt.id == *excerpt_id {
2137                return Some((excerpt.buffer_id, &excerpt.buffer));
2138            }
2139        }
2140        None
2141    }
2142
2143    pub fn remote_selections_in_range<'a>(
2144        &'a self,
2145        range: &'a Range<Anchor>,
2146    ) -> impl 'a + Iterator<Item = (ReplicaId, Selection<Anchor>)> {
2147        let mut cursor = self.excerpts.cursor::<Option<&ExcerptId>>();
2148        cursor.seek(&Some(&range.start.excerpt_id), Bias::Left, &());
2149        cursor
2150            .take_while(move |excerpt| excerpt.id <= range.end.excerpt_id)
2151            .flat_map(move |excerpt| {
2152                let mut query_range = excerpt.range.start.clone()..excerpt.range.end.clone();
2153                if excerpt.id == range.start.excerpt_id {
2154                    query_range.start = range.start.text_anchor.clone();
2155                }
2156                if excerpt.id == range.end.excerpt_id {
2157                    query_range.end = range.end.text_anchor.clone();
2158                }
2159
2160                excerpt
2161                    .buffer
2162                    .remote_selections_in_range(query_range)
2163                    .flat_map(move |(replica_id, selections)| {
2164                        selections.map(move |selection| {
2165                            let mut start = Anchor {
2166                                buffer_id: excerpt.buffer_id,
2167                                excerpt_id: excerpt.id.clone(),
2168                                text_anchor: selection.start.clone(),
2169                            };
2170                            let mut end = Anchor {
2171                                buffer_id: excerpt.buffer_id,
2172                                excerpt_id: excerpt.id.clone(),
2173                                text_anchor: selection.end.clone(),
2174                            };
2175                            if range.start.cmp(&start, self).unwrap().is_gt() {
2176                                start = range.start.clone();
2177                            }
2178                            if range.end.cmp(&end, self).unwrap().is_lt() {
2179                                end = range.end.clone();
2180                            }
2181
2182                            (
2183                                replica_id,
2184                                Selection {
2185                                    id: selection.id,
2186                                    start,
2187                                    end,
2188                                    reversed: selection.reversed,
2189                                    goal: selection.goal,
2190                                },
2191                            )
2192                        })
2193                    })
2194            })
2195    }
2196}
2197
2198impl History {
2199    fn start_transaction(&mut self, now: Instant) -> Option<TransactionId> {
2200        self.transaction_depth += 1;
2201        if self.transaction_depth == 1 {
2202            let id = self.next_transaction_id.tick();
2203            self.undo_stack.push(Transaction {
2204                id,
2205                buffer_transactions: Default::default(),
2206                first_edit_at: now,
2207                last_edit_at: now,
2208            });
2209            Some(id)
2210        } else {
2211            None
2212        }
2213    }
2214
2215    fn end_transaction(
2216        &mut self,
2217        now: Instant,
2218        buffer_transactions: HashSet<(usize, TransactionId)>,
2219    ) -> bool {
2220        assert_ne!(self.transaction_depth, 0);
2221        self.transaction_depth -= 1;
2222        if self.transaction_depth == 0 {
2223            if buffer_transactions.is_empty() {
2224                self.undo_stack.pop();
2225                false
2226            } else {
2227                let transaction = self.undo_stack.last_mut().unwrap();
2228                transaction.last_edit_at = now;
2229                transaction.buffer_transactions.extend(buffer_transactions);
2230                true
2231            }
2232        } else {
2233            false
2234        }
2235    }
2236
2237    fn pop_undo(&mut self) -> Option<&Transaction> {
2238        assert_eq!(self.transaction_depth, 0);
2239        if let Some(transaction) = self.undo_stack.pop() {
2240            self.redo_stack.push(transaction);
2241            self.redo_stack.last()
2242        } else {
2243            None
2244        }
2245    }
2246
2247    fn pop_redo(&mut self) -> Option<&Transaction> {
2248        assert_eq!(self.transaction_depth, 0);
2249        if let Some(transaction) = self.redo_stack.pop() {
2250            self.undo_stack.push(transaction);
2251            self.undo_stack.last()
2252        } else {
2253            None
2254        }
2255    }
2256
2257    fn group(&mut self) -> Option<TransactionId> {
2258        let mut new_len = self.undo_stack.len();
2259        let mut transactions = self.undo_stack.iter_mut();
2260
2261        if let Some(mut transaction) = transactions.next_back() {
2262            while let Some(prev_transaction) = transactions.next_back() {
2263                if transaction.first_edit_at - prev_transaction.last_edit_at <= self.group_interval
2264                {
2265                    transaction = prev_transaction;
2266                    new_len -= 1;
2267                } else {
2268                    break;
2269                }
2270            }
2271        }
2272
2273        let (transactions_to_keep, transactions_to_merge) = self.undo_stack.split_at_mut(new_len);
2274        if let Some(last_transaction) = transactions_to_keep.last_mut() {
2275            if let Some(transaction) = transactions_to_merge.last() {
2276                last_transaction.last_edit_at = transaction.last_edit_at;
2277            }
2278        }
2279
2280        self.undo_stack.truncate(new_len);
2281        self.undo_stack.last().map(|t| t.id)
2282    }
2283}
2284
2285impl Excerpt {
2286    fn new(
2287        id: ExcerptId,
2288        buffer_id: usize,
2289        buffer: BufferSnapshot,
2290        range: Range<text::Anchor>,
2291        has_trailing_newline: bool,
2292    ) -> Self {
2293        Excerpt {
2294            id,
2295            max_buffer_row: range.end.to_point(&buffer).row,
2296            text_summary: buffer.text_summary_for_range::<TextSummary, _>(range.to_offset(&buffer)),
2297            buffer_id,
2298            buffer,
2299            range,
2300            has_trailing_newline,
2301        }
2302    }
2303
2304    fn chunks_in_range<'a>(
2305        &'a self,
2306        range: Range<usize>,
2307        language_aware: bool,
2308    ) -> ExcerptChunks<'a> {
2309        let content_start = self.range.start.to_offset(&self.buffer);
2310        let chunks_start = content_start + range.start;
2311        let chunks_end = content_start + cmp::min(range.end, self.text_summary.bytes);
2312
2313        let footer_height = if self.has_trailing_newline
2314            && range.start <= self.text_summary.bytes
2315            && range.end > self.text_summary.bytes
2316        {
2317            1
2318        } else {
2319            0
2320        };
2321
2322        let content_chunks = self.buffer.chunks(chunks_start..chunks_end, language_aware);
2323
2324        ExcerptChunks {
2325            content_chunks,
2326            footer_height,
2327        }
2328    }
2329
2330    fn bytes_in_range(&self, range: Range<usize>) -> ExcerptBytes {
2331        let content_start = self.range.start.to_offset(&self.buffer);
2332        let bytes_start = content_start + range.start;
2333        let bytes_end = content_start + cmp::min(range.end, self.text_summary.bytes);
2334        let footer_height = if self.has_trailing_newline
2335            && range.start <= self.text_summary.bytes
2336            && range.end > self.text_summary.bytes
2337        {
2338            1
2339        } else {
2340            0
2341        };
2342        let content_bytes = self.buffer.bytes_in_range(bytes_start..bytes_end);
2343
2344        ExcerptBytes {
2345            content_bytes,
2346            footer_height,
2347        }
2348    }
2349
2350    fn clip_anchor(&self, text_anchor: text::Anchor) -> text::Anchor {
2351        if text_anchor
2352            .cmp(&self.range.start, &self.buffer)
2353            .unwrap()
2354            .is_lt()
2355        {
2356            self.range.start.clone()
2357        } else if text_anchor
2358            .cmp(&self.range.end, &self.buffer)
2359            .unwrap()
2360            .is_gt()
2361        {
2362            self.range.end.clone()
2363        } else {
2364            text_anchor
2365        }
2366    }
2367
2368    fn contains(&self, anchor: &Anchor) -> bool {
2369        self.buffer_id == anchor.buffer_id
2370            && self
2371                .range
2372                .start
2373                .cmp(&anchor.text_anchor, &self.buffer)
2374                .unwrap()
2375                .is_le()
2376            && self
2377                .range
2378                .end
2379                .cmp(&anchor.text_anchor, &self.buffer)
2380                .unwrap()
2381                .is_ge()
2382    }
2383}
2384
2385impl fmt::Debug for Excerpt {
2386    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2387        f.debug_struct("Excerpt")
2388            .field("id", &self.id)
2389            .field("buffer_id", &self.buffer_id)
2390            .field("range", &self.range)
2391            .field("text_summary", &self.text_summary)
2392            .field("has_trailing_newline", &self.has_trailing_newline)
2393            .finish()
2394    }
2395}
2396
2397impl sum_tree::Item for Excerpt {
2398    type Summary = ExcerptSummary;
2399
2400    fn summary(&self) -> Self::Summary {
2401        let mut text = self.text_summary.clone();
2402        if self.has_trailing_newline {
2403            text += TextSummary::from("\n");
2404        }
2405        ExcerptSummary {
2406            excerpt_id: self.id.clone(),
2407            max_buffer_row: self.max_buffer_row,
2408            text,
2409        }
2410    }
2411}
2412
2413impl sum_tree::Summary for ExcerptSummary {
2414    type Context = ();
2415
2416    fn add_summary(&mut self, summary: &Self, _: &()) {
2417        debug_assert!(summary.excerpt_id > self.excerpt_id);
2418        self.excerpt_id = summary.excerpt_id.clone();
2419        self.text.add_summary(&summary.text, &());
2420        self.max_buffer_row = cmp::max(self.max_buffer_row, summary.max_buffer_row);
2421    }
2422}
2423
2424impl<'a> sum_tree::Dimension<'a, ExcerptSummary> for TextSummary {
2425    fn add_summary(&mut self, summary: &'a ExcerptSummary, _: &()) {
2426        *self += &summary.text;
2427    }
2428}
2429
2430impl<'a> sum_tree::Dimension<'a, ExcerptSummary> for usize {
2431    fn add_summary(&mut self, summary: &'a ExcerptSummary, _: &()) {
2432        *self += summary.text.bytes;
2433    }
2434}
2435
2436impl<'a> sum_tree::SeekTarget<'a, ExcerptSummary, ExcerptSummary> for usize {
2437    fn cmp(&self, cursor_location: &ExcerptSummary, _: &()) -> cmp::Ordering {
2438        Ord::cmp(self, &cursor_location.text.bytes)
2439    }
2440}
2441
2442impl<'a> sum_tree::SeekTarget<'a, ExcerptSummary, ExcerptSummary> for Option<&'a ExcerptId> {
2443    fn cmp(&self, cursor_location: &ExcerptSummary, _: &()) -> cmp::Ordering {
2444        Ord::cmp(self, &Some(&cursor_location.excerpt_id))
2445    }
2446}
2447
2448impl<'a> sum_tree::Dimension<'a, ExcerptSummary> for Point {
2449    fn add_summary(&mut self, summary: &'a ExcerptSummary, _: &()) {
2450        *self += summary.text.lines;
2451    }
2452}
2453
2454impl<'a> sum_tree::Dimension<'a, ExcerptSummary> for PointUtf16 {
2455    fn add_summary(&mut self, summary: &'a ExcerptSummary, _: &()) {
2456        *self += summary.text.lines_utf16
2457    }
2458}
2459
2460impl<'a> sum_tree::Dimension<'a, ExcerptSummary> for Option<&'a ExcerptId> {
2461    fn add_summary(&mut self, summary: &'a ExcerptSummary, _: &()) {
2462        *self = Some(&summary.excerpt_id);
2463    }
2464}
2465
2466impl<'a> MultiBufferRows<'a> {
2467    pub fn seek(&mut self, row: u32) {
2468        self.buffer_row_range = 0..0;
2469
2470        self.excerpts
2471            .seek_forward(&Point::new(row, 0), Bias::Right, &());
2472        if self.excerpts.item().is_none() {
2473            self.excerpts.prev(&());
2474
2475            if self.excerpts.item().is_none() && row == 0 {
2476                self.buffer_row_range = 0..1;
2477                return;
2478            }
2479        }
2480
2481        if let Some(excerpt) = self.excerpts.item() {
2482            let overshoot = row - self.excerpts.start().row;
2483            let excerpt_start = excerpt.range.start.to_point(&excerpt.buffer).row;
2484            self.buffer_row_range.start = excerpt_start + overshoot;
2485            self.buffer_row_range.end = excerpt_start + excerpt.text_summary.lines.row + 1;
2486        }
2487    }
2488}
2489
2490impl<'a> Iterator for MultiBufferRows<'a> {
2491    type Item = Option<u32>;
2492
2493    fn next(&mut self) -> Option<Self::Item> {
2494        loop {
2495            if !self.buffer_row_range.is_empty() {
2496                let row = Some(self.buffer_row_range.start);
2497                self.buffer_row_range.start += 1;
2498                return Some(row);
2499            }
2500            self.excerpts.item()?;
2501            self.excerpts.next(&());
2502            let excerpt = self.excerpts.item()?;
2503            self.buffer_row_range.start = excerpt.range.start.to_point(&excerpt.buffer).row;
2504            self.buffer_row_range.end =
2505                self.buffer_row_range.start + excerpt.text_summary.lines.row + 1;
2506        }
2507    }
2508}
2509
2510impl<'a> MultiBufferChunks<'a> {
2511    pub fn offset(&self) -> usize {
2512        self.range.start
2513    }
2514
2515    pub fn seek(&mut self, offset: usize) {
2516        self.range.start = offset;
2517        self.excerpts.seek(&offset, Bias::Right, &());
2518        if let Some(excerpt) = self.excerpts.item() {
2519            self.excerpt_chunks = Some(excerpt.chunks_in_range(
2520                self.range.start - self.excerpts.start()..self.range.end - self.excerpts.start(),
2521                self.language_aware,
2522            ));
2523        } else {
2524            self.excerpt_chunks = None;
2525        }
2526    }
2527}
2528
2529impl<'a> Iterator for MultiBufferChunks<'a> {
2530    type Item = Chunk<'a>;
2531
2532    fn next(&mut self) -> Option<Self::Item> {
2533        if self.range.is_empty() {
2534            None
2535        } else if let Some(chunk) = self.excerpt_chunks.as_mut()?.next() {
2536            self.range.start += chunk.text.len();
2537            Some(chunk)
2538        } else {
2539            self.excerpts.next(&());
2540            let excerpt = self.excerpts.item()?;
2541            self.excerpt_chunks = Some(excerpt.chunks_in_range(
2542                0..self.range.end - self.excerpts.start(),
2543                self.language_aware,
2544            ));
2545            self.next()
2546        }
2547    }
2548}
2549
2550impl<'a> MultiBufferBytes<'a> {
2551    fn consume(&mut self, len: usize) {
2552        self.range.start += len;
2553        self.chunk = &self.chunk[len..];
2554
2555        if !self.range.is_empty() && self.chunk.is_empty() {
2556            if let Some(chunk) = self.excerpt_bytes.as_mut().and_then(|bytes| bytes.next()) {
2557                self.chunk = chunk;
2558            } else {
2559                self.excerpts.next(&());
2560                if let Some(excerpt) = self.excerpts.item() {
2561                    let mut excerpt_bytes =
2562                        excerpt.bytes_in_range(0..self.range.end - self.excerpts.start());
2563                    self.chunk = excerpt_bytes.next().unwrap();
2564                    self.excerpt_bytes = Some(excerpt_bytes);
2565                }
2566            }
2567        }
2568    }
2569}
2570
2571impl<'a> Iterator for MultiBufferBytes<'a> {
2572    type Item = &'a [u8];
2573
2574    fn next(&mut self) -> Option<Self::Item> {
2575        let chunk = self.chunk;
2576        if chunk.is_empty() {
2577            None
2578        } else {
2579            self.consume(chunk.len());
2580            Some(chunk)
2581        }
2582    }
2583}
2584
2585impl<'a> io::Read for MultiBufferBytes<'a> {
2586    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
2587        let len = cmp::min(buf.len(), self.chunk.len());
2588        buf[..len].copy_from_slice(&self.chunk[..len]);
2589        if len > 0 {
2590            self.consume(len);
2591        }
2592        Ok(len)
2593    }
2594}
2595
2596impl<'a> Iterator for ExcerptBytes<'a> {
2597    type Item = &'a [u8];
2598
2599    fn next(&mut self) -> Option<Self::Item> {
2600        if let Some(chunk) = self.content_bytes.next() {
2601            if !chunk.is_empty() {
2602                return Some(chunk);
2603            }
2604        }
2605
2606        if self.footer_height > 0 {
2607            let result = &NEWLINES[..self.footer_height];
2608            self.footer_height = 0;
2609            return Some(result);
2610        }
2611
2612        None
2613    }
2614}
2615
2616impl<'a> Iterator for ExcerptChunks<'a> {
2617    type Item = Chunk<'a>;
2618
2619    fn next(&mut self) -> Option<Self::Item> {
2620        if let Some(chunk) = self.content_chunks.next() {
2621            return Some(chunk);
2622        }
2623
2624        if self.footer_height > 0 {
2625            let text = unsafe { str::from_utf8_unchecked(&NEWLINES[..self.footer_height]) };
2626            self.footer_height = 0;
2627            return Some(Chunk {
2628                text,
2629                ..Default::default()
2630            });
2631        }
2632
2633        None
2634    }
2635}
2636
2637impl ToOffset for Point {
2638    fn to_offset<'a>(&self, snapshot: &MultiBufferSnapshot) -> usize {
2639        snapshot.point_to_offset(*self)
2640    }
2641}
2642
2643impl ToOffset for PointUtf16 {
2644    fn to_offset<'a>(&self, snapshot: &MultiBufferSnapshot) -> usize {
2645        snapshot.point_utf16_to_offset(*self)
2646    }
2647}
2648
2649impl ToOffset for usize {
2650    fn to_offset<'a>(&self, snapshot: &MultiBufferSnapshot) -> usize {
2651        assert!(*self <= snapshot.len(), "offset is out of range");
2652        *self
2653    }
2654}
2655
2656impl ToPoint for usize {
2657    fn to_point<'a>(&self, snapshot: &MultiBufferSnapshot) -> Point {
2658        snapshot.offset_to_point(*self)
2659    }
2660}
2661
2662impl ToPoint for Point {
2663    fn to_point<'a>(&self, _: &MultiBufferSnapshot) -> Point {
2664        *self
2665    }
2666}
2667
2668impl ToPointUtf16 for usize {
2669    fn to_point_utf16<'a>(&self, snapshot: &MultiBufferSnapshot) -> PointUtf16 {
2670        snapshot.offset_to_point_utf16(*self)
2671    }
2672}
2673
2674impl ToPointUtf16 for Point {
2675    fn to_point_utf16<'a>(&self, snapshot: &MultiBufferSnapshot) -> PointUtf16 {
2676        snapshot.point_to_point_utf16(*self)
2677    }
2678}
2679
2680impl ToPointUtf16 for PointUtf16 {
2681    fn to_point_utf16<'a>(&self, _: &MultiBufferSnapshot) -> PointUtf16 {
2682        *self
2683    }
2684}
2685
2686pub fn char_kind(c: char) -> CharKind {
2687    if c == '\n' {
2688        CharKind::Newline
2689    } else if c.is_whitespace() {
2690        CharKind::Whitespace
2691    } else if c.is_alphanumeric() || c == '_' {
2692        CharKind::Word
2693    } else {
2694        CharKind::Punctuation
2695    }
2696}
2697
2698#[cfg(test)]
2699mod tests {
2700    use super::*;
2701    use gpui::MutableAppContext;
2702    use language::{Buffer, Rope};
2703    use rand::prelude::*;
2704    use std::env;
2705    use text::{Point, RandomCharIter};
2706    use util::test::sample_text;
2707
2708    #[gpui::test]
2709    fn test_singleton_multibuffer(cx: &mut MutableAppContext) {
2710        let buffer = cx.add_model(|cx| Buffer::new(0, sample_text(6, 6, 'a'), cx));
2711        let multibuffer = cx.add_model(|cx| MultiBuffer::singleton(buffer.clone(), cx));
2712
2713        let snapshot = multibuffer.read(cx).snapshot(cx);
2714        assert_eq!(snapshot.text(), buffer.read(cx).text());
2715
2716        assert_eq!(
2717            snapshot.buffer_rows(0).collect::<Vec<_>>(),
2718            (0..buffer.read(cx).row_count())
2719                .map(Some)
2720                .collect::<Vec<_>>()
2721        );
2722
2723        buffer.update(cx, |buffer, cx| buffer.edit([1..3], "XXX\n", cx));
2724        let snapshot = multibuffer.read(cx).snapshot(cx);
2725
2726        assert_eq!(snapshot.text(), buffer.read(cx).text());
2727        assert_eq!(
2728            snapshot.buffer_rows(0).collect::<Vec<_>>(),
2729            (0..buffer.read(cx).row_count())
2730                .map(Some)
2731                .collect::<Vec<_>>()
2732        );
2733    }
2734
2735    #[gpui::test]
2736    fn test_remote_multibuffer(cx: &mut MutableAppContext) {
2737        let host_buffer = cx.add_model(|cx| Buffer::new(0, "a", cx));
2738        let guest_buffer = cx.add_model(|cx| {
2739            let message = host_buffer.read(cx).to_proto();
2740            Buffer::from_proto(1, message, None, cx).unwrap()
2741        });
2742        let multibuffer = cx.add_model(|cx| MultiBuffer::singleton(guest_buffer.clone(), cx));
2743        let snapshot = multibuffer.read(cx).snapshot(cx);
2744        assert_eq!(snapshot.text(), "a");
2745
2746        guest_buffer.update(cx, |buffer, cx| buffer.edit([1..1], "b", cx));
2747        let snapshot = multibuffer.read(cx).snapshot(cx);
2748        assert_eq!(snapshot.text(), "ab");
2749
2750        guest_buffer.update(cx, |buffer, cx| buffer.edit([2..2], "c", cx));
2751        let snapshot = multibuffer.read(cx).snapshot(cx);
2752        assert_eq!(snapshot.text(), "abc");
2753    }
2754
2755    #[gpui::test]
2756    fn test_excerpt_buffer(cx: &mut MutableAppContext) {
2757        let buffer_1 = cx.add_model(|cx| Buffer::new(0, sample_text(6, 6, 'a'), cx));
2758        let buffer_2 = cx.add_model(|cx| Buffer::new(0, sample_text(6, 6, 'g'), cx));
2759        let multibuffer = cx.add_model(|_| MultiBuffer::new(0));
2760
2761        let subscription = multibuffer.update(cx, |multibuffer, cx| {
2762            let subscription = multibuffer.subscribe();
2763            multibuffer.push_excerpts(buffer_1.clone(), [Point::new(1, 2)..Point::new(2, 5)], cx);
2764            assert_eq!(
2765                subscription.consume().into_inner(),
2766                [Edit {
2767                    old: 0..0,
2768                    new: 0..10
2769                }]
2770            );
2771
2772            multibuffer.push_excerpts(buffer_1.clone(), [Point::new(3, 3)..Point::new(4, 4)], cx);
2773            multibuffer.push_excerpts(buffer_2.clone(), [Point::new(3, 1)..Point::new(3, 3)], cx);
2774            assert_eq!(
2775                subscription.consume().into_inner(),
2776                [Edit {
2777                    old: 10..10,
2778                    new: 10..22
2779                }]
2780            );
2781
2782            subscription
2783        });
2784
2785        let snapshot = multibuffer.read(cx).snapshot(cx);
2786        assert_eq!(
2787            snapshot.text(),
2788            concat!(
2789                "bbbb\n",  // Preserve newlines
2790                "ccccc\n", //
2791                "ddd\n",   //
2792                "eeee\n",  //
2793                "jj"       //
2794            )
2795        );
2796        assert_eq!(
2797            snapshot.buffer_rows(0).collect::<Vec<_>>(),
2798            [Some(1), Some(2), Some(3), Some(4), Some(3)]
2799        );
2800        assert_eq!(
2801            snapshot.buffer_rows(2).collect::<Vec<_>>(),
2802            [Some(3), Some(4), Some(3)]
2803        );
2804        assert_eq!(snapshot.buffer_rows(4).collect::<Vec<_>>(), [Some(3)]);
2805        assert_eq!(snapshot.buffer_rows(5).collect::<Vec<_>>(), []);
2806
2807        assert_eq!(
2808            boundaries_in_range(Point::new(0, 0)..Point::new(4, 2), &snapshot),
2809            &[
2810                (0, "bbbb\nccccc".to_string(), true),
2811                (2, "ddd\neeee".to_string(), false),
2812                (4, "jj".to_string(), true),
2813            ]
2814        );
2815        assert_eq!(
2816            boundaries_in_range(Point::new(0, 0)..Point::new(2, 0), &snapshot),
2817            &[(0, "bbbb\nccccc".to_string(), true)]
2818        );
2819        assert_eq!(
2820            boundaries_in_range(Point::new(1, 0)..Point::new(1, 5), &snapshot),
2821            &[]
2822        );
2823        assert_eq!(
2824            boundaries_in_range(Point::new(1, 0)..Point::new(2, 0), &snapshot),
2825            &[]
2826        );
2827        assert_eq!(
2828            boundaries_in_range(Point::new(1, 0)..Point::new(4, 0), &snapshot),
2829            &[(2, "ddd\neeee".to_string(), false)]
2830        );
2831        assert_eq!(
2832            boundaries_in_range(Point::new(1, 0)..Point::new(4, 0), &snapshot),
2833            &[(2, "ddd\neeee".to_string(), false)]
2834        );
2835        assert_eq!(
2836            boundaries_in_range(Point::new(2, 0)..Point::new(3, 0), &snapshot),
2837            &[(2, "ddd\neeee".to_string(), false)]
2838        );
2839        assert_eq!(
2840            boundaries_in_range(Point::new(4, 0)..Point::new(4, 2), &snapshot),
2841            &[(4, "jj".to_string(), true)]
2842        );
2843        assert_eq!(
2844            boundaries_in_range(Point::new(4, 2)..Point::new(4, 2), &snapshot),
2845            &[]
2846        );
2847
2848        buffer_1.update(cx, |buffer, cx| {
2849            buffer.edit(
2850                [
2851                    Point::new(0, 0)..Point::new(0, 0),
2852                    Point::new(2, 1)..Point::new(2, 3),
2853                ],
2854                "\n",
2855                cx,
2856            );
2857        });
2858
2859        let snapshot = multibuffer.read(cx).snapshot(cx);
2860        assert_eq!(
2861            snapshot.text(),
2862            concat!(
2863                "bbbb\n", // Preserve newlines
2864                "c\n",    //
2865                "cc\n",   //
2866                "ddd\n",  //
2867                "eeee\n", //
2868                "jj"      //
2869            )
2870        );
2871
2872        assert_eq!(
2873            subscription.consume().into_inner(),
2874            [Edit {
2875                old: 6..8,
2876                new: 6..7
2877            }]
2878        );
2879
2880        let snapshot = multibuffer.read(cx).snapshot(cx);
2881        assert_eq!(
2882            snapshot.clip_point(Point::new(0, 5), Bias::Left),
2883            Point::new(0, 4)
2884        );
2885        assert_eq!(
2886            snapshot.clip_point(Point::new(0, 5), Bias::Right),
2887            Point::new(0, 4)
2888        );
2889        assert_eq!(
2890            snapshot.clip_point(Point::new(5, 1), Bias::Right),
2891            Point::new(5, 1)
2892        );
2893        assert_eq!(
2894            snapshot.clip_point(Point::new(5, 2), Bias::Right),
2895            Point::new(5, 2)
2896        );
2897        assert_eq!(
2898            snapshot.clip_point(Point::new(5, 3), Bias::Right),
2899            Point::new(5, 2)
2900        );
2901
2902        let snapshot = multibuffer.update(cx, |multibuffer, cx| {
2903            let buffer_2_excerpt_id = multibuffer.excerpt_ids_for_buffer(&buffer_2)[0].clone();
2904            multibuffer.remove_excerpts(&[buffer_2_excerpt_id], cx);
2905            multibuffer.snapshot(cx)
2906        });
2907
2908        assert_eq!(
2909            snapshot.text(),
2910            concat!(
2911                "bbbb\n", // Preserve newlines
2912                "c\n",    //
2913                "cc\n",   //
2914                "ddd\n",  //
2915                "eeee",   //
2916            )
2917        );
2918
2919        fn boundaries_in_range(
2920            range: Range<Point>,
2921            snapshot: &MultiBufferSnapshot,
2922        ) -> Vec<(u32, String, bool)> {
2923            snapshot
2924                .excerpt_boundaries_in_range(range)
2925                .map(|boundary| {
2926                    (
2927                        boundary.row,
2928                        boundary
2929                            .buffer
2930                            .text_for_range(boundary.range)
2931                            .collect::<String>(),
2932                        boundary.starts_new_buffer,
2933                    )
2934                })
2935                .collect::<Vec<_>>()
2936        }
2937    }
2938
2939    #[gpui::test]
2940    fn test_excerpts_with_context_lines(cx: &mut MutableAppContext) {
2941        let buffer = cx.add_model(|cx| Buffer::new(0, sample_text(20, 3, 'a'), cx));
2942        let multibuffer = cx.add_model(|_| MultiBuffer::new(0));
2943        let anchor_ranges = multibuffer.update(cx, |multibuffer, cx| {
2944            multibuffer.push_excerpts_with_context_lines(
2945                buffer.clone(),
2946                vec![
2947                    Point::new(3, 2)..Point::new(4, 2),
2948                    Point::new(7, 1)..Point::new(7, 3),
2949                    Point::new(15, 0)..Point::new(15, 0),
2950                ],
2951                2,
2952                cx,
2953            )
2954        });
2955
2956        let snapshot = multibuffer.read(cx).snapshot(cx);
2957        assert_eq!(
2958            snapshot.text(),
2959            "bbb\nccc\nddd\neee\nfff\nggg\nhhh\niii\njjj\n\nnnn\nooo\nppp\nqqq\nrrr\n"
2960        );
2961
2962        assert_eq!(
2963            anchor_ranges
2964                .iter()
2965                .map(|range| range.to_point(&snapshot))
2966                .collect::<Vec<_>>(),
2967            vec![
2968                Point::new(2, 2)..Point::new(3, 2),
2969                Point::new(6, 1)..Point::new(6, 3),
2970                Point::new(12, 0)..Point::new(12, 0)
2971            ]
2972        );
2973    }
2974
2975    #[gpui::test]
2976    fn test_empty_excerpt_buffer(cx: &mut MutableAppContext) {
2977        let multibuffer = cx.add_model(|_| MultiBuffer::new(0));
2978
2979        let snapshot = multibuffer.read(cx).snapshot(cx);
2980        assert_eq!(snapshot.text(), "");
2981        assert_eq!(snapshot.buffer_rows(0).collect::<Vec<_>>(), &[Some(0)]);
2982        assert_eq!(snapshot.buffer_rows(1).collect::<Vec<_>>(), &[]);
2983    }
2984
2985    #[gpui::test]
2986    fn test_singleton_multibuffer_anchors(cx: &mut MutableAppContext) {
2987        let buffer = cx.add_model(|cx| Buffer::new(0, "abcd", cx));
2988        let multibuffer = cx.add_model(|cx| MultiBuffer::singleton(buffer.clone(), cx));
2989        let old_snapshot = multibuffer.read(cx).snapshot(cx);
2990        buffer.update(cx, |buffer, cx| {
2991            buffer.edit([0..0], "X", cx);
2992            buffer.edit([5..5], "Y", cx);
2993        });
2994        let new_snapshot = multibuffer.read(cx).snapshot(cx);
2995
2996        assert_eq!(old_snapshot.text(), "abcd");
2997        assert_eq!(new_snapshot.text(), "XabcdY");
2998
2999        assert_eq!(old_snapshot.anchor_before(0).to_offset(&new_snapshot), 0);
3000        assert_eq!(old_snapshot.anchor_after(0).to_offset(&new_snapshot), 1);
3001        assert_eq!(old_snapshot.anchor_before(4).to_offset(&new_snapshot), 5);
3002        assert_eq!(old_snapshot.anchor_after(4).to_offset(&new_snapshot), 6);
3003    }
3004
3005    #[gpui::test]
3006    fn test_multibuffer_anchors(cx: &mut MutableAppContext) {
3007        let buffer_1 = cx.add_model(|cx| Buffer::new(0, "abcd", cx));
3008        let buffer_2 = cx.add_model(|cx| Buffer::new(0, "efghi", cx));
3009        let multibuffer = cx.add_model(|cx| {
3010            let mut multibuffer = MultiBuffer::new(0);
3011            multibuffer.push_excerpts(buffer_1.clone(), [0..4], cx);
3012            multibuffer.push_excerpts(buffer_2.clone(), [0..5], cx);
3013            multibuffer
3014        });
3015        let old_snapshot = multibuffer.read(cx).snapshot(cx);
3016
3017        assert_eq!(old_snapshot.anchor_before(0).to_offset(&old_snapshot), 0);
3018        assert_eq!(old_snapshot.anchor_after(0).to_offset(&old_snapshot), 0);
3019        assert_eq!(Anchor::min().to_offset(&old_snapshot), 0);
3020        assert_eq!(Anchor::min().to_offset(&old_snapshot), 0);
3021        assert_eq!(Anchor::max().to_offset(&old_snapshot), 10);
3022        assert_eq!(Anchor::max().to_offset(&old_snapshot), 10);
3023
3024        buffer_1.update(cx, |buffer, cx| {
3025            buffer.edit([0..0], "W", cx);
3026            buffer.edit([5..5], "X", cx);
3027        });
3028        buffer_2.update(cx, |buffer, cx| {
3029            buffer.edit([0..0], "Y", cx);
3030            buffer.edit([6..0], "Z", cx);
3031        });
3032        let new_snapshot = multibuffer.read(cx).snapshot(cx);
3033
3034        assert_eq!(old_snapshot.text(), "abcd\nefghi");
3035        assert_eq!(new_snapshot.text(), "WabcdX\nYefghiZ");
3036
3037        assert_eq!(old_snapshot.anchor_before(0).to_offset(&new_snapshot), 0);
3038        assert_eq!(old_snapshot.anchor_after(0).to_offset(&new_snapshot), 1);
3039        assert_eq!(old_snapshot.anchor_before(1).to_offset(&new_snapshot), 2);
3040        assert_eq!(old_snapshot.anchor_after(1).to_offset(&new_snapshot), 2);
3041        assert_eq!(old_snapshot.anchor_before(2).to_offset(&new_snapshot), 3);
3042        assert_eq!(old_snapshot.anchor_after(2).to_offset(&new_snapshot), 3);
3043        assert_eq!(old_snapshot.anchor_before(5).to_offset(&new_snapshot), 7);
3044        assert_eq!(old_snapshot.anchor_after(5).to_offset(&new_snapshot), 8);
3045        assert_eq!(old_snapshot.anchor_before(10).to_offset(&new_snapshot), 13);
3046        assert_eq!(old_snapshot.anchor_after(10).to_offset(&new_snapshot), 14);
3047    }
3048
3049    #[gpui::test]
3050    fn test_multibuffer_resolving_anchors_after_replacing_their_excerpts(
3051        cx: &mut MutableAppContext,
3052    ) {
3053        let buffer_1 = cx.add_model(|cx| Buffer::new(0, "abcd", cx));
3054        let buffer_2 = cx.add_model(|cx| Buffer::new(0, "ABCDEFGHIJKLMNOP", cx));
3055        let multibuffer = cx.add_model(|_| MultiBuffer::new(0));
3056
3057        // Create an insertion id in buffer 1 that doesn't exist in buffer 2.
3058        // Add an excerpt from buffer 1 that spans this new insertion.
3059        buffer_1.update(cx, |buffer, cx| buffer.edit([4..4], "123", cx));
3060        let excerpt_id_1 = multibuffer.update(cx, |multibuffer, cx| {
3061            multibuffer
3062                .push_excerpts(buffer_1.clone(), [0..7], cx)
3063                .pop()
3064                .unwrap()
3065        });
3066
3067        let snapshot_1 = multibuffer.read(cx).snapshot(cx);
3068        assert_eq!(snapshot_1.text(), "abcd123");
3069
3070        // Replace the buffer 1 excerpt with new excerpts from buffer 2.
3071        let (excerpt_id_2, excerpt_id_3) = multibuffer.update(cx, |multibuffer, cx| {
3072            multibuffer.remove_excerpts([&excerpt_id_1], cx);
3073            let mut ids = multibuffer
3074                .push_excerpts(buffer_2.clone(), [0..4, 6..10, 12..16], cx)
3075                .into_iter();
3076            (ids.next().unwrap(), ids.next().unwrap())
3077        });
3078        let snapshot_2 = multibuffer.read(cx).snapshot(cx);
3079        assert_eq!(snapshot_2.text(), "ABCD\nGHIJ\nMNOP");
3080
3081        // The old excerpt id has been reused.
3082        assert_eq!(excerpt_id_2, excerpt_id_1);
3083
3084        // Resolve some anchors from the previous snapshot in the new snapshot.
3085        // Although there is still an excerpt with the same id, it is for
3086        // a different buffer, so we don't attempt to resolve the old text
3087        // anchor in the new buffer.
3088        assert_eq!(
3089            snapshot_2.summary_for_anchor::<usize>(&snapshot_1.anchor_before(2)),
3090            0
3091        );
3092        assert_eq!(
3093            snapshot_2.summaries_for_anchors::<usize, _>(&[
3094                snapshot_1.anchor_before(2),
3095                snapshot_1.anchor_after(3)
3096            ]),
3097            vec![0, 0]
3098        );
3099        let refresh =
3100            snapshot_2.refresh_anchors(&[snapshot_1.anchor_before(2), snapshot_1.anchor_after(3)]);
3101        assert_eq!(
3102            refresh,
3103            &[
3104                (0, snapshot_2.anchor_before(0), false),
3105                (1, snapshot_2.anchor_after(0), false),
3106            ]
3107        );
3108
3109        // Replace the middle excerpt with a smaller excerpt in buffer 2,
3110        // that intersects the old excerpt.
3111        let excerpt_id_5 = multibuffer.update(cx, |multibuffer, cx| {
3112            multibuffer.remove_excerpts([&excerpt_id_3], cx);
3113            multibuffer
3114                .insert_excerpts_after(&excerpt_id_3, buffer_2.clone(), [5..8], cx)
3115                .pop()
3116                .unwrap()
3117        });
3118
3119        let snapshot_3 = multibuffer.read(cx).snapshot(cx);
3120        assert_eq!(snapshot_3.text(), "ABCD\nFGH\nMNOP");
3121        assert_ne!(excerpt_id_5, excerpt_id_3);
3122
3123        // Resolve some anchors from the previous snapshot in the new snapshot.
3124        // The anchor in the middle excerpt snaps to the beginning of the
3125        // excerpt, since it is not
3126        let anchors = [
3127            snapshot_2.anchor_before(0),
3128            snapshot_2.anchor_after(2),
3129            snapshot_2.anchor_after(6),
3130            snapshot_2.anchor_after(14),
3131        ];
3132        assert_eq!(
3133            snapshot_3.summaries_for_anchors::<usize, _>(&anchors),
3134            &[0, 2, 9, 13]
3135        );
3136
3137        let new_anchors = snapshot_3.refresh_anchors(&anchors);
3138        assert_eq!(
3139            new_anchors.iter().map(|a| (a.0, a.2)).collect::<Vec<_>>(),
3140            &[(0, true), (1, true), (2, true), (3, true)]
3141        );
3142        assert_eq!(
3143            snapshot_3.summaries_for_anchors::<usize, _>(new_anchors.iter().map(|a| &a.1)),
3144            &[0, 2, 7, 13]
3145        );
3146    }
3147
3148    #[gpui::test(iterations = 100)]
3149    fn test_random_multibuffer(cx: &mut MutableAppContext, mut rng: StdRng) {
3150        let operations = env::var("OPERATIONS")
3151            .map(|i| i.parse().expect("invalid `OPERATIONS` variable"))
3152            .unwrap_or(10);
3153
3154        let mut buffers: Vec<ModelHandle<Buffer>> = Vec::new();
3155        let multibuffer = cx.add_model(|_| MultiBuffer::new(0));
3156        let mut excerpt_ids = Vec::new();
3157        let mut expected_excerpts = Vec::<(ModelHandle<Buffer>, Range<text::Anchor>)>::new();
3158        let mut anchors = Vec::new();
3159        let mut old_versions = Vec::new();
3160
3161        for _ in 0..operations {
3162            match rng.gen_range(0..100) {
3163                0..=19 if !buffers.is_empty() => {
3164                    let buffer = buffers.choose(&mut rng).unwrap();
3165                    buffer.update(cx, |buf, cx| buf.randomly_edit(&mut rng, 5, cx));
3166                }
3167                20..=29 if !expected_excerpts.is_empty() => {
3168                    let mut ids_to_remove = vec![];
3169                    for _ in 0..rng.gen_range(1..=3) {
3170                        if expected_excerpts.is_empty() {
3171                            break;
3172                        }
3173
3174                        let ix = rng.gen_range(0..expected_excerpts.len());
3175                        ids_to_remove.push(excerpt_ids.remove(ix));
3176                        let (buffer, range) = expected_excerpts.remove(ix);
3177                        let buffer = buffer.read(cx);
3178                        log::info!(
3179                            "Removing excerpt {}: {:?}",
3180                            ix,
3181                            buffer
3182                                .text_for_range(range.to_offset(&buffer))
3183                                .collect::<String>(),
3184                        );
3185                    }
3186                    ids_to_remove.sort_unstable();
3187                    multibuffer.update(cx, |multibuffer, cx| {
3188                        multibuffer.remove_excerpts(&ids_to_remove, cx)
3189                    });
3190                }
3191                30..=39 if !expected_excerpts.is_empty() => {
3192                    let multibuffer = multibuffer.read(cx).read(cx);
3193                    let offset =
3194                        multibuffer.clip_offset(rng.gen_range(0..=multibuffer.len()), Bias::Left);
3195                    let bias = if rng.gen() { Bias::Left } else { Bias::Right };
3196                    log::info!("Creating anchor at {} with bias {:?}", offset, bias);
3197                    anchors.push(multibuffer.anchor_at(offset, bias));
3198                    anchors.sort_by(|a, b| a.cmp(&b, &multibuffer).unwrap());
3199                }
3200                40..=44 if !anchors.is_empty() => {
3201                    let multibuffer = multibuffer.read(cx).read(cx);
3202
3203                    anchors = multibuffer
3204                        .refresh_anchors(&anchors)
3205                        .into_iter()
3206                        .map(|a| a.1)
3207                        .collect();
3208
3209                    // Ensure the newly-refreshed anchors point to a valid excerpt and don't
3210                    // overshoot its boundaries.
3211                    let mut cursor = multibuffer.excerpts.cursor::<Option<&ExcerptId>>();
3212                    for anchor in &anchors {
3213                        if anchor.excerpt_id == ExcerptId::min()
3214                            || anchor.excerpt_id == ExcerptId::max()
3215                        {
3216                            continue;
3217                        }
3218
3219                        cursor.seek_forward(&Some(&anchor.excerpt_id), Bias::Left, &());
3220                        let excerpt = cursor.item().unwrap();
3221                        assert_eq!(excerpt.id, anchor.excerpt_id);
3222                        assert!(excerpt.contains(anchor));
3223                    }
3224                }
3225                _ => {
3226                    let buffer_handle = if buffers.is_empty() || rng.gen_bool(0.4) {
3227                        let base_text = RandomCharIter::new(&mut rng).take(10).collect::<String>();
3228                        buffers.push(cx.add_model(|cx| Buffer::new(0, base_text, cx)));
3229                        buffers.last().unwrap()
3230                    } else {
3231                        buffers.choose(&mut rng).unwrap()
3232                    };
3233
3234                    let buffer = buffer_handle.read(cx);
3235                    let end_ix = buffer.clip_offset(rng.gen_range(0..=buffer.len()), Bias::Right);
3236                    let start_ix = buffer.clip_offset(rng.gen_range(0..=end_ix), Bias::Left);
3237                    let anchor_range = buffer.anchor_before(start_ix)..buffer.anchor_after(end_ix);
3238                    let prev_excerpt_ix = rng.gen_range(0..=expected_excerpts.len());
3239                    let prev_excerpt_id = excerpt_ids
3240                        .get(prev_excerpt_ix)
3241                        .cloned()
3242                        .unwrap_or(ExcerptId::max());
3243                    let excerpt_ix = (prev_excerpt_ix + 1).min(expected_excerpts.len());
3244
3245                    log::info!(
3246                        "Inserting excerpt at {} of {} for buffer {}: {:?}[{:?}] = {:?}",
3247                        excerpt_ix,
3248                        expected_excerpts.len(),
3249                        buffer_handle.id(),
3250                        buffer.text(),
3251                        start_ix..end_ix,
3252                        &buffer.text()[start_ix..end_ix]
3253                    );
3254
3255                    let excerpt_id = multibuffer.update(cx, |multibuffer, cx| {
3256                        multibuffer
3257                            .insert_excerpts_after(
3258                                &prev_excerpt_id,
3259                                buffer_handle.clone(),
3260                                [start_ix..end_ix],
3261                                cx,
3262                            )
3263                            .pop()
3264                            .unwrap()
3265                    });
3266
3267                    excerpt_ids.insert(excerpt_ix, excerpt_id);
3268                    expected_excerpts.insert(excerpt_ix, (buffer_handle.clone(), anchor_range));
3269                }
3270            }
3271
3272            if rng.gen_bool(0.3) {
3273                multibuffer.update(cx, |multibuffer, cx| {
3274                    old_versions.push((multibuffer.snapshot(cx), multibuffer.subscribe()));
3275                })
3276            }
3277
3278            let snapshot = multibuffer.read(cx).snapshot(cx);
3279
3280            let mut excerpt_starts = Vec::new();
3281            let mut expected_text = String::new();
3282            let mut expected_buffer_rows = Vec::new();
3283            for (buffer, range) in &expected_excerpts {
3284                let buffer = buffer.read(cx);
3285                let buffer_range = range.to_offset(buffer);
3286
3287                excerpt_starts.push(TextSummary::from(expected_text.as_str()));
3288                expected_text.extend(buffer.text_for_range(buffer_range.clone()));
3289                expected_text.push('\n');
3290
3291                let buffer_row_range = buffer.offset_to_point(buffer_range.start).row
3292                    ..=buffer.offset_to_point(buffer_range.end).row;
3293                for row in buffer_row_range {
3294                    expected_buffer_rows.push(Some(row));
3295                }
3296            }
3297            // Remove final trailing newline.
3298            if !expected_excerpts.is_empty() {
3299                expected_text.pop();
3300            }
3301
3302            // Always report one buffer row
3303            if expected_buffer_rows.is_empty() {
3304                expected_buffer_rows.push(Some(0));
3305            }
3306
3307            assert_eq!(snapshot.text(), expected_text);
3308            log::info!("MultiBuffer text: {:?}", expected_text);
3309
3310            assert_eq!(
3311                snapshot.buffer_rows(0).collect::<Vec<_>>(),
3312                expected_buffer_rows,
3313            );
3314
3315            for _ in 0..5 {
3316                let start_row = rng.gen_range(0..=expected_buffer_rows.len());
3317                assert_eq!(
3318                    snapshot.buffer_rows(start_row as u32).collect::<Vec<_>>(),
3319                    &expected_buffer_rows[start_row..],
3320                    "buffer_rows({})",
3321                    start_row
3322                );
3323            }
3324
3325            assert_eq!(
3326                snapshot.max_buffer_row(),
3327                expected_buffer_rows
3328                    .into_iter()
3329                    .filter_map(|r| r)
3330                    .max()
3331                    .unwrap()
3332            );
3333
3334            let mut excerpt_starts = excerpt_starts.into_iter();
3335            for (buffer, range) in &expected_excerpts {
3336                let buffer_id = buffer.id();
3337                let buffer = buffer.read(cx);
3338                let buffer_range = range.to_offset(buffer);
3339                let buffer_start_point = buffer.offset_to_point(buffer_range.start);
3340                let buffer_start_point_utf16 =
3341                    buffer.text_summary_for_range::<PointUtf16, _>(0..buffer_range.start);
3342
3343                let excerpt_start = excerpt_starts.next().unwrap();
3344                let mut offset = excerpt_start.bytes;
3345                let mut buffer_offset = buffer_range.start;
3346                let mut point = excerpt_start.lines;
3347                let mut buffer_point = buffer_start_point;
3348                let mut point_utf16 = excerpt_start.lines_utf16;
3349                let mut buffer_point_utf16 = buffer_start_point_utf16;
3350                for ch in buffer
3351                    .snapshot()
3352                    .chunks(buffer_range.clone(), false)
3353                    .flat_map(|c| c.text.chars())
3354                {
3355                    for _ in 0..ch.len_utf8() {
3356                        let left_offset = snapshot.clip_offset(offset, Bias::Left);
3357                        let right_offset = snapshot.clip_offset(offset, Bias::Right);
3358                        let buffer_left_offset = buffer.clip_offset(buffer_offset, Bias::Left);
3359                        let buffer_right_offset = buffer.clip_offset(buffer_offset, Bias::Right);
3360                        assert_eq!(
3361                            left_offset,
3362                            excerpt_start.bytes + (buffer_left_offset - buffer_range.start),
3363                            "clip_offset({:?}, Left). buffer: {:?}, buffer offset: {:?}",
3364                            offset,
3365                            buffer_id,
3366                            buffer_offset,
3367                        );
3368                        assert_eq!(
3369                            right_offset,
3370                            excerpt_start.bytes + (buffer_right_offset - buffer_range.start),
3371                            "clip_offset({:?}, Right). buffer: {:?}, buffer offset: {:?}",
3372                            offset,
3373                            buffer_id,
3374                            buffer_offset,
3375                        );
3376
3377                        let left_point = snapshot.clip_point(point, Bias::Left);
3378                        let right_point = snapshot.clip_point(point, Bias::Right);
3379                        let buffer_left_point = buffer.clip_point(buffer_point, Bias::Left);
3380                        let buffer_right_point = buffer.clip_point(buffer_point, Bias::Right);
3381                        assert_eq!(
3382                            left_point,
3383                            excerpt_start.lines + (buffer_left_point - buffer_start_point),
3384                            "clip_point({:?}, Left). buffer: {:?}, buffer point: {:?}",
3385                            point,
3386                            buffer_id,
3387                            buffer_point,
3388                        );
3389                        assert_eq!(
3390                            right_point,
3391                            excerpt_start.lines + (buffer_right_point - buffer_start_point),
3392                            "clip_point({:?}, Right). buffer: {:?}, buffer point: {:?}",
3393                            point,
3394                            buffer_id,
3395                            buffer_point,
3396                        );
3397
3398                        assert_eq!(
3399                            snapshot.point_to_offset(left_point),
3400                            left_offset,
3401                            "point_to_offset({:?})",
3402                            left_point,
3403                        );
3404                        assert_eq!(
3405                            snapshot.offset_to_point(left_offset),
3406                            left_point,
3407                            "offset_to_point({:?})",
3408                            left_offset,
3409                        );
3410
3411                        offset += 1;
3412                        buffer_offset += 1;
3413                        if ch == '\n' {
3414                            point += Point::new(1, 0);
3415                            buffer_point += Point::new(1, 0);
3416                        } else {
3417                            point += Point::new(0, 1);
3418                            buffer_point += Point::new(0, 1);
3419                        }
3420                    }
3421
3422                    for _ in 0..ch.len_utf16() {
3423                        let left_point_utf16 = snapshot.clip_point_utf16(point_utf16, Bias::Left);
3424                        let right_point_utf16 = snapshot.clip_point_utf16(point_utf16, Bias::Right);
3425                        let buffer_left_point_utf16 =
3426                            buffer.clip_point_utf16(buffer_point_utf16, Bias::Left);
3427                        let buffer_right_point_utf16 =
3428                            buffer.clip_point_utf16(buffer_point_utf16, Bias::Right);
3429                        assert_eq!(
3430                            left_point_utf16,
3431                            excerpt_start.lines_utf16
3432                                + (buffer_left_point_utf16 - buffer_start_point_utf16),
3433                            "clip_point_utf16({:?}, Left). buffer: {:?}, buffer point_utf16: {:?}",
3434                            point_utf16,
3435                            buffer_id,
3436                            buffer_point_utf16,
3437                        );
3438                        assert_eq!(
3439                            right_point_utf16,
3440                            excerpt_start.lines_utf16
3441                                + (buffer_right_point_utf16 - buffer_start_point_utf16),
3442                            "clip_point_utf16({:?}, Right). buffer: {:?}, buffer point_utf16: {:?}",
3443                            point_utf16,
3444                            buffer_id,
3445                            buffer_point_utf16,
3446                        );
3447
3448                        if ch == '\n' {
3449                            point_utf16 += PointUtf16::new(1, 0);
3450                            buffer_point_utf16 += PointUtf16::new(1, 0);
3451                        } else {
3452                            point_utf16 += PointUtf16::new(0, 1);
3453                            buffer_point_utf16 += PointUtf16::new(0, 1);
3454                        }
3455                    }
3456                }
3457            }
3458
3459            for (row, line) in expected_text.split('\n').enumerate() {
3460                assert_eq!(
3461                    snapshot.line_len(row as u32),
3462                    line.len() as u32,
3463                    "line_len({}).",
3464                    row
3465                );
3466            }
3467
3468            let text_rope = Rope::from(expected_text.as_str());
3469            for _ in 0..10 {
3470                let end_ix = text_rope.clip_offset(rng.gen_range(0..=text_rope.len()), Bias::Right);
3471                let start_ix = text_rope.clip_offset(rng.gen_range(0..=end_ix), Bias::Left);
3472
3473                let text_for_range = snapshot
3474                    .text_for_range(start_ix..end_ix)
3475                    .collect::<String>();
3476                assert_eq!(
3477                    text_for_range,
3478                    &expected_text[start_ix..end_ix],
3479                    "incorrect text for range {:?}",
3480                    start_ix..end_ix
3481                );
3482
3483                let excerpted_buffer_ranges =
3484                    multibuffer.read(cx).excerpted_buffers(start_ix..end_ix, cx);
3485                let excerpted_buffers_text = excerpted_buffer_ranges
3486                    .into_iter()
3487                    .map(|(buffer, buffer_range)| {
3488                        buffer
3489                            .read(cx)
3490                            .text_for_range(buffer_range)
3491                            .collect::<String>()
3492                    })
3493                    .collect::<Vec<_>>()
3494                    .join("\n");
3495                assert_eq!(excerpted_buffers_text, text_for_range);
3496
3497                let expected_summary = TextSummary::from(&expected_text[start_ix..end_ix]);
3498                assert_eq!(
3499                    snapshot.text_summary_for_range::<TextSummary, _>(start_ix..end_ix),
3500                    expected_summary,
3501                    "incorrect summary for range {:?}",
3502                    start_ix..end_ix
3503                );
3504            }
3505
3506            // Anchor resolution
3507            for (anchor, resolved_offset) in anchors
3508                .iter()
3509                .zip(snapshot.summaries_for_anchors::<usize, _>(&anchors))
3510            {
3511                assert!(resolved_offset <= snapshot.len());
3512                assert_eq!(
3513                    snapshot.summary_for_anchor::<usize>(anchor),
3514                    resolved_offset
3515                );
3516            }
3517
3518            for _ in 0..10 {
3519                let end_ix = text_rope.clip_offset(rng.gen_range(0..=text_rope.len()), Bias::Right);
3520                assert_eq!(
3521                    snapshot.reversed_chars_at(end_ix).collect::<String>(),
3522                    expected_text[..end_ix].chars().rev().collect::<String>(),
3523                );
3524            }
3525
3526            for _ in 0..10 {
3527                let end_ix = rng.gen_range(0..=text_rope.len());
3528                let start_ix = rng.gen_range(0..=end_ix);
3529                assert_eq!(
3530                    snapshot
3531                        .bytes_in_range(start_ix..end_ix)
3532                        .flatten()
3533                        .copied()
3534                        .collect::<Vec<_>>(),
3535                    expected_text.as_bytes()[start_ix..end_ix].to_vec(),
3536                    "bytes_in_range({:?})",
3537                    start_ix..end_ix,
3538                );
3539            }
3540        }
3541
3542        let snapshot = multibuffer.read(cx).snapshot(cx);
3543        for (old_snapshot, subscription) in old_versions {
3544            let edits = subscription.consume().into_inner();
3545
3546            log::info!(
3547                "applying subscription edits to old text: {:?}: {:?}",
3548                old_snapshot.text(),
3549                edits,
3550            );
3551
3552            let mut text = old_snapshot.text();
3553            for edit in edits {
3554                let new_text: String = snapshot.text_for_range(edit.new.clone()).collect();
3555                text.replace_range(edit.new.start..edit.new.start + edit.old.len(), &new_text);
3556            }
3557            assert_eq!(text.to_string(), snapshot.text());
3558        }
3559    }
3560
3561    #[gpui::test]
3562    fn test_history(cx: &mut MutableAppContext) {
3563        let buffer_1 = cx.add_model(|cx| Buffer::new(0, "1234", cx));
3564        let buffer_2 = cx.add_model(|cx| Buffer::new(0, "5678", cx));
3565        let multibuffer = cx.add_model(|_| MultiBuffer::new(0));
3566        let group_interval = multibuffer.read(cx).history.group_interval;
3567        multibuffer.update(cx, |multibuffer, cx| {
3568            multibuffer.push_excerpts(buffer_1.clone(), [0..buffer_1.read(cx).len()], cx);
3569            multibuffer.push_excerpts(buffer_2.clone(), [0..buffer_2.read(cx).len()], cx);
3570        });
3571
3572        let mut now = Instant::now();
3573
3574        multibuffer.update(cx, |multibuffer, cx| {
3575            multibuffer.start_transaction_at(now, cx);
3576            multibuffer.edit(
3577                [
3578                    Point::new(0, 0)..Point::new(0, 0),
3579                    Point::new(1, 0)..Point::new(1, 0),
3580                ],
3581                "A",
3582                cx,
3583            );
3584            multibuffer.edit(
3585                [
3586                    Point::new(0, 1)..Point::new(0, 1),
3587                    Point::new(1, 1)..Point::new(1, 1),
3588                ],
3589                "B",
3590                cx,
3591            );
3592            multibuffer.end_transaction_at(now, cx);
3593            assert_eq!(multibuffer.read(cx).text(), "AB1234\nAB5678");
3594
3595            now += 2 * group_interval;
3596            multibuffer.start_transaction_at(now, cx);
3597            multibuffer.edit([2..2], "C", cx);
3598            multibuffer.end_transaction_at(now, cx);
3599            assert_eq!(multibuffer.read(cx).text(), "ABC1234\nAB5678");
3600
3601            multibuffer.undo(cx);
3602            assert_eq!(multibuffer.read(cx).text(), "AB1234\nAB5678");
3603
3604            multibuffer.undo(cx);
3605            assert_eq!(multibuffer.read(cx).text(), "1234\n5678");
3606
3607            multibuffer.redo(cx);
3608            assert_eq!(multibuffer.read(cx).text(), "AB1234\nAB5678");
3609
3610            multibuffer.redo(cx);
3611            assert_eq!(multibuffer.read(cx).text(), "ABC1234\nAB5678");
3612
3613            buffer_1.update(cx, |buffer_1, cx| buffer_1.undo(cx));
3614            assert_eq!(multibuffer.read(cx).text(), "AB1234\nAB5678");
3615
3616            multibuffer.undo(cx);
3617            assert_eq!(multibuffer.read(cx).text(), "1234\n5678");
3618
3619            multibuffer.redo(cx);
3620            assert_eq!(multibuffer.read(cx).text(), "AB1234\nAB5678");
3621
3622            multibuffer.redo(cx);
3623            assert_eq!(multibuffer.read(cx).text(), "ABC1234\nAB5678");
3624
3625            multibuffer.undo(cx);
3626            assert_eq!(multibuffer.read(cx).text(), "AB1234\nAB5678");
3627
3628            buffer_1.update(cx, |buffer_1, cx| buffer_1.redo(cx));
3629            assert_eq!(multibuffer.read(cx).text(), "ABC1234\nAB5678");
3630
3631            multibuffer.undo(cx);
3632            assert_eq!(multibuffer.read(cx).text(), "C1234\n5678");
3633        });
3634    }
3635}