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