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                let transaction = self.undo_stack.last_mut().unwrap();
2483                transaction.last_edit_at = now;
2484                for (buffer_id, transaction_id) in buffer_transactions {
2485                    transaction
2486                        .buffer_transactions
2487                        .entry(buffer_id)
2488                        .or_insert(transaction_id);
2489                }
2490                true
2491            }
2492        } else {
2493            false
2494        }
2495    }
2496
2497    fn push_transaction<'a, T>(&mut self, buffer_transactions: T, now: Instant)
2498    where
2499        T: IntoIterator<Item = (&'a ModelHandle<Buffer>, &'a language::Transaction)>,
2500    {
2501        assert_eq!(self.transaction_depth, 0);
2502        let transaction = Transaction {
2503            id: self.next_transaction_id.tick(),
2504            buffer_transactions: buffer_transactions
2505                .into_iter()
2506                .map(|(buffer, transaction)| (buffer.id(), transaction.id))
2507                .collect(),
2508            first_edit_at: now,
2509            last_edit_at: now,
2510            suppress_grouping: false,
2511        };
2512        if !transaction.buffer_transactions.is_empty() {
2513            self.undo_stack.push(transaction);
2514        }
2515    }
2516
2517    fn finalize_last_transaction(&mut self) {
2518        if let Some(transaction) = self.undo_stack.last_mut() {
2519            transaction.suppress_grouping = true;
2520        }
2521    }
2522
2523    fn pop_undo(&mut self) -> Option<&mut Transaction> {
2524        assert_eq!(self.transaction_depth, 0);
2525        if let Some(transaction) = self.undo_stack.pop() {
2526            self.redo_stack.push(transaction);
2527            self.redo_stack.last_mut()
2528        } else {
2529            None
2530        }
2531    }
2532
2533    fn pop_redo(&mut self) -> Option<&mut Transaction> {
2534        assert_eq!(self.transaction_depth, 0);
2535        if let Some(transaction) = self.redo_stack.pop() {
2536            self.undo_stack.push(transaction);
2537            self.undo_stack.last_mut()
2538        } else {
2539            None
2540        }
2541    }
2542
2543    fn group(&mut self) -> Option<TransactionId> {
2544        let mut new_len = self.undo_stack.len();
2545        let mut transactions = self.undo_stack.iter_mut();
2546
2547        if let Some(mut transaction) = transactions.next_back() {
2548            while let Some(prev_transaction) = transactions.next_back() {
2549                if !prev_transaction.suppress_grouping
2550                    && transaction.first_edit_at - prev_transaction.last_edit_at
2551                        <= self.group_interval
2552                {
2553                    transaction = prev_transaction;
2554                    new_len -= 1;
2555                } else {
2556                    break;
2557                }
2558            }
2559        }
2560
2561        let (transactions_to_keep, transactions_to_merge) = self.undo_stack.split_at_mut(new_len);
2562        if let Some(last_transaction) = transactions_to_keep.last_mut() {
2563            if let Some(transaction) = transactions_to_merge.last() {
2564                last_transaction.last_edit_at = transaction.last_edit_at;
2565            }
2566            for to_merge in transactions_to_merge {
2567                for (buffer_id, transaction_id) in &to_merge.buffer_transactions {
2568                    last_transaction
2569                        .buffer_transactions
2570                        .entry(*buffer_id)
2571                        .or_insert(*transaction_id);
2572                }
2573            }
2574        }
2575
2576        self.undo_stack.truncate(new_len);
2577        self.undo_stack.last().map(|t| t.id)
2578    }
2579}
2580
2581impl Excerpt {
2582    fn new(
2583        id: ExcerptId,
2584        buffer_id: usize,
2585        buffer: BufferSnapshot,
2586        range: Range<text::Anchor>,
2587        has_trailing_newline: bool,
2588    ) -> Self {
2589        Excerpt {
2590            id,
2591            max_buffer_row: range.end.to_point(&buffer).row,
2592            text_summary: buffer.text_summary_for_range::<TextSummary, _>(range.to_offset(&buffer)),
2593            buffer_id,
2594            buffer,
2595            range,
2596            has_trailing_newline,
2597        }
2598    }
2599
2600    fn chunks_in_range<'a>(
2601        &'a self,
2602        range: Range<usize>,
2603        language_aware: bool,
2604    ) -> ExcerptChunks<'a> {
2605        let content_start = self.range.start.to_offset(&self.buffer);
2606        let chunks_start = content_start + range.start;
2607        let chunks_end = content_start + cmp::min(range.end, self.text_summary.bytes);
2608
2609        let footer_height = if self.has_trailing_newline
2610            && range.start <= self.text_summary.bytes
2611            && range.end > self.text_summary.bytes
2612        {
2613            1
2614        } else {
2615            0
2616        };
2617
2618        let content_chunks = self.buffer.chunks(chunks_start..chunks_end, language_aware);
2619
2620        ExcerptChunks {
2621            content_chunks,
2622            footer_height,
2623        }
2624    }
2625
2626    fn bytes_in_range(&self, range: Range<usize>) -> ExcerptBytes {
2627        let content_start = self.range.start.to_offset(&self.buffer);
2628        let bytes_start = content_start + range.start;
2629        let bytes_end = content_start + cmp::min(range.end, self.text_summary.bytes);
2630        let footer_height = if self.has_trailing_newline
2631            && range.start <= self.text_summary.bytes
2632            && range.end > self.text_summary.bytes
2633        {
2634            1
2635        } else {
2636            0
2637        };
2638        let content_bytes = self.buffer.bytes_in_range(bytes_start..bytes_end);
2639
2640        ExcerptBytes {
2641            content_bytes,
2642            footer_height,
2643        }
2644    }
2645
2646    fn clip_anchor(&self, text_anchor: text::Anchor) -> text::Anchor {
2647        if text_anchor.cmp(&self.range.start, &self.buffer).is_lt() {
2648            self.range.start.clone()
2649        } else if text_anchor.cmp(&self.range.end, &self.buffer).is_gt() {
2650            self.range.end.clone()
2651        } else {
2652            text_anchor
2653        }
2654    }
2655
2656    fn contains(&self, anchor: &Anchor) -> bool {
2657        Some(self.buffer_id) == anchor.buffer_id
2658            && self
2659                .range
2660                .start
2661                .cmp(&anchor.text_anchor, &self.buffer)
2662                .is_le()
2663            && self
2664                .range
2665                .end
2666                .cmp(&anchor.text_anchor, &self.buffer)
2667                .is_ge()
2668    }
2669}
2670
2671impl fmt::Debug for Excerpt {
2672    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2673        f.debug_struct("Excerpt")
2674            .field("id", &self.id)
2675            .field("buffer_id", &self.buffer_id)
2676            .field("range", &self.range)
2677            .field("text_summary", &self.text_summary)
2678            .field("has_trailing_newline", &self.has_trailing_newline)
2679            .finish()
2680    }
2681}
2682
2683impl sum_tree::Item for Excerpt {
2684    type Summary = ExcerptSummary;
2685
2686    fn summary(&self) -> Self::Summary {
2687        let mut text = self.text_summary.clone();
2688        if self.has_trailing_newline {
2689            text += TextSummary::from("\n");
2690        }
2691        ExcerptSummary {
2692            excerpt_id: self.id.clone(),
2693            max_buffer_row: self.max_buffer_row,
2694            text,
2695        }
2696    }
2697}
2698
2699impl sum_tree::Summary for ExcerptSummary {
2700    type Context = ();
2701
2702    fn add_summary(&mut self, summary: &Self, _: &()) {
2703        debug_assert!(summary.excerpt_id > self.excerpt_id);
2704        self.excerpt_id = summary.excerpt_id.clone();
2705        self.text.add_summary(&summary.text, &());
2706        self.max_buffer_row = cmp::max(self.max_buffer_row, summary.max_buffer_row);
2707    }
2708}
2709
2710impl<'a> sum_tree::Dimension<'a, ExcerptSummary> for TextSummary {
2711    fn add_summary(&mut self, summary: &'a ExcerptSummary, _: &()) {
2712        *self += &summary.text;
2713    }
2714}
2715
2716impl<'a> sum_tree::Dimension<'a, ExcerptSummary> for usize {
2717    fn add_summary(&mut self, summary: &'a ExcerptSummary, _: &()) {
2718        *self += summary.text.bytes;
2719    }
2720}
2721
2722impl<'a> sum_tree::SeekTarget<'a, ExcerptSummary, ExcerptSummary> for usize {
2723    fn cmp(&self, cursor_location: &ExcerptSummary, _: &()) -> cmp::Ordering {
2724        Ord::cmp(self, &cursor_location.text.bytes)
2725    }
2726}
2727
2728impl<'a> sum_tree::SeekTarget<'a, ExcerptSummary, ExcerptSummary> for Option<&'a ExcerptId> {
2729    fn cmp(&self, cursor_location: &ExcerptSummary, _: &()) -> cmp::Ordering {
2730        Ord::cmp(self, &Some(&cursor_location.excerpt_id))
2731    }
2732}
2733
2734impl<'a> sum_tree::Dimension<'a, ExcerptSummary> for Point {
2735    fn add_summary(&mut self, summary: &'a ExcerptSummary, _: &()) {
2736        *self += summary.text.lines;
2737    }
2738}
2739
2740impl<'a> sum_tree::Dimension<'a, ExcerptSummary> for PointUtf16 {
2741    fn add_summary(&mut self, summary: &'a ExcerptSummary, _: &()) {
2742        *self += summary.text.lines_utf16
2743    }
2744}
2745
2746impl<'a> sum_tree::Dimension<'a, ExcerptSummary> for Option<&'a ExcerptId> {
2747    fn add_summary(&mut self, summary: &'a ExcerptSummary, _: &()) {
2748        *self = Some(&summary.excerpt_id);
2749    }
2750}
2751
2752impl<'a> MultiBufferRows<'a> {
2753    pub fn seek(&mut self, row: u32) {
2754        self.buffer_row_range = 0..0;
2755
2756        self.excerpts
2757            .seek_forward(&Point::new(row, 0), Bias::Right, &());
2758        if self.excerpts.item().is_none() {
2759            self.excerpts.prev(&());
2760
2761            if self.excerpts.item().is_none() && row == 0 {
2762                self.buffer_row_range = 0..1;
2763                return;
2764            }
2765        }
2766
2767        if let Some(excerpt) = self.excerpts.item() {
2768            let overshoot = row - self.excerpts.start().row;
2769            let excerpt_start = excerpt.range.start.to_point(&excerpt.buffer).row;
2770            self.buffer_row_range.start = excerpt_start + overshoot;
2771            self.buffer_row_range.end = excerpt_start + excerpt.text_summary.lines.row + 1;
2772        }
2773    }
2774}
2775
2776impl<'a> Iterator for MultiBufferRows<'a> {
2777    type Item = Option<u32>;
2778
2779    fn next(&mut self) -> Option<Self::Item> {
2780        loop {
2781            if !self.buffer_row_range.is_empty() {
2782                let row = Some(self.buffer_row_range.start);
2783                self.buffer_row_range.start += 1;
2784                return Some(row);
2785            }
2786            self.excerpts.item()?;
2787            self.excerpts.next(&());
2788            let excerpt = self.excerpts.item()?;
2789            self.buffer_row_range.start = excerpt.range.start.to_point(&excerpt.buffer).row;
2790            self.buffer_row_range.end =
2791                self.buffer_row_range.start + excerpt.text_summary.lines.row + 1;
2792        }
2793    }
2794}
2795
2796impl<'a> MultiBufferChunks<'a> {
2797    pub fn offset(&self) -> usize {
2798        self.range.start
2799    }
2800
2801    pub fn seek(&mut self, offset: usize) {
2802        self.range.start = offset;
2803        self.excerpts.seek(&offset, Bias::Right, &());
2804        if let Some(excerpt) = self.excerpts.item() {
2805            self.excerpt_chunks = Some(excerpt.chunks_in_range(
2806                self.range.start - self.excerpts.start()..self.range.end - self.excerpts.start(),
2807                self.language_aware,
2808            ));
2809        } else {
2810            self.excerpt_chunks = None;
2811        }
2812    }
2813}
2814
2815impl<'a> Iterator for MultiBufferChunks<'a> {
2816    type Item = Chunk<'a>;
2817
2818    fn next(&mut self) -> Option<Self::Item> {
2819        if self.range.is_empty() {
2820            None
2821        } else if let Some(chunk) = self.excerpt_chunks.as_mut()?.next() {
2822            self.range.start += chunk.text.len();
2823            Some(chunk)
2824        } else {
2825            self.excerpts.next(&());
2826            let excerpt = self.excerpts.item()?;
2827            self.excerpt_chunks = Some(excerpt.chunks_in_range(
2828                0..self.range.end - self.excerpts.start(),
2829                self.language_aware,
2830            ));
2831            self.next()
2832        }
2833    }
2834}
2835
2836impl<'a> MultiBufferBytes<'a> {
2837    fn consume(&mut self, len: usize) {
2838        self.range.start += len;
2839        self.chunk = &self.chunk[len..];
2840
2841        if !self.range.is_empty() && self.chunk.is_empty() {
2842            if let Some(chunk) = self.excerpt_bytes.as_mut().and_then(|bytes| bytes.next()) {
2843                self.chunk = chunk;
2844            } else {
2845                self.excerpts.next(&());
2846                if let Some(excerpt) = self.excerpts.item() {
2847                    let mut excerpt_bytes =
2848                        excerpt.bytes_in_range(0..self.range.end - self.excerpts.start());
2849                    self.chunk = excerpt_bytes.next().unwrap();
2850                    self.excerpt_bytes = Some(excerpt_bytes);
2851                }
2852            }
2853        }
2854    }
2855}
2856
2857impl<'a> Iterator for MultiBufferBytes<'a> {
2858    type Item = &'a [u8];
2859
2860    fn next(&mut self) -> Option<Self::Item> {
2861        let chunk = self.chunk;
2862        if chunk.is_empty() {
2863            None
2864        } else {
2865            self.consume(chunk.len());
2866            Some(chunk)
2867        }
2868    }
2869}
2870
2871impl<'a> io::Read for MultiBufferBytes<'a> {
2872    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
2873        let len = cmp::min(buf.len(), self.chunk.len());
2874        buf[..len].copy_from_slice(&self.chunk[..len]);
2875        if len > 0 {
2876            self.consume(len);
2877        }
2878        Ok(len)
2879    }
2880}
2881
2882impl<'a> Iterator for ExcerptBytes<'a> {
2883    type Item = &'a [u8];
2884
2885    fn next(&mut self) -> Option<Self::Item> {
2886        if let Some(chunk) = self.content_bytes.next() {
2887            if !chunk.is_empty() {
2888                return Some(chunk);
2889            }
2890        }
2891
2892        if self.footer_height > 0 {
2893            let result = &NEWLINES[..self.footer_height];
2894            self.footer_height = 0;
2895            return Some(result);
2896        }
2897
2898        None
2899    }
2900}
2901
2902impl<'a> Iterator for ExcerptChunks<'a> {
2903    type Item = Chunk<'a>;
2904
2905    fn next(&mut self) -> Option<Self::Item> {
2906        if let Some(chunk) = self.content_chunks.next() {
2907            return Some(chunk);
2908        }
2909
2910        if self.footer_height > 0 {
2911            let text = unsafe { str::from_utf8_unchecked(&NEWLINES[..self.footer_height]) };
2912            self.footer_height = 0;
2913            return Some(Chunk {
2914                text,
2915                ..Default::default()
2916            });
2917        }
2918
2919        None
2920    }
2921}
2922
2923impl ToOffset for Point {
2924    fn to_offset<'a>(&self, snapshot: &MultiBufferSnapshot) -> usize {
2925        snapshot.point_to_offset(*self)
2926    }
2927}
2928
2929impl ToOffset for PointUtf16 {
2930    fn to_offset<'a>(&self, snapshot: &MultiBufferSnapshot) -> usize {
2931        snapshot.point_utf16_to_offset(*self)
2932    }
2933}
2934
2935impl ToOffset for usize {
2936    fn to_offset<'a>(&self, snapshot: &MultiBufferSnapshot) -> usize {
2937        assert!(*self <= snapshot.len(), "offset is out of range");
2938        *self
2939    }
2940}
2941
2942impl ToPoint for usize {
2943    fn to_point<'a>(&self, snapshot: &MultiBufferSnapshot) -> Point {
2944        snapshot.offset_to_point(*self)
2945    }
2946}
2947
2948impl ToPoint for Point {
2949    fn to_point<'a>(&self, _: &MultiBufferSnapshot) -> Point {
2950        *self
2951    }
2952}
2953
2954impl ToPointUtf16 for usize {
2955    fn to_point_utf16<'a>(&self, snapshot: &MultiBufferSnapshot) -> PointUtf16 {
2956        snapshot.offset_to_point_utf16(*self)
2957    }
2958}
2959
2960impl ToPointUtf16 for Point {
2961    fn to_point_utf16<'a>(&self, snapshot: &MultiBufferSnapshot) -> PointUtf16 {
2962        snapshot.point_to_point_utf16(*self)
2963    }
2964}
2965
2966impl ToPointUtf16 for PointUtf16 {
2967    fn to_point_utf16<'a>(&self, _: &MultiBufferSnapshot) -> PointUtf16 {
2968        *self
2969    }
2970}
2971
2972#[cfg(test)]
2973mod tests {
2974    use super::*;
2975    use gpui::MutableAppContext;
2976    use language::{Buffer, Rope};
2977    use rand::prelude::*;
2978    use std::{env, rc::Rc};
2979    use text::{Point, RandomCharIter};
2980    use util::test::sample_text;
2981
2982    #[gpui::test]
2983    fn test_singleton_multibuffer(cx: &mut MutableAppContext) {
2984        let buffer = cx.add_model(|cx| Buffer::new(0, sample_text(6, 6, 'a'), cx));
2985        let multibuffer = cx.add_model(|cx| MultiBuffer::singleton(buffer.clone(), cx));
2986
2987        let snapshot = multibuffer.read(cx).snapshot(cx);
2988        assert_eq!(snapshot.text(), buffer.read(cx).text());
2989
2990        assert_eq!(
2991            snapshot.buffer_rows(0).collect::<Vec<_>>(),
2992            (0..buffer.read(cx).row_count())
2993                .map(Some)
2994                .collect::<Vec<_>>()
2995        );
2996
2997        buffer.update(cx, |buffer, cx| buffer.edit([(1..3, "XXX\n")], cx));
2998        let snapshot = multibuffer.read(cx).snapshot(cx);
2999
3000        assert_eq!(snapshot.text(), buffer.read(cx).text());
3001        assert_eq!(
3002            snapshot.buffer_rows(0).collect::<Vec<_>>(),
3003            (0..buffer.read(cx).row_count())
3004                .map(Some)
3005                .collect::<Vec<_>>()
3006        );
3007    }
3008
3009    #[gpui::test]
3010    fn test_remote_multibuffer(cx: &mut MutableAppContext) {
3011        let host_buffer = cx.add_model(|cx| Buffer::new(0, "a", cx));
3012        let guest_buffer = cx.add_model(|cx| {
3013            let message = host_buffer.read(cx).to_proto();
3014            Buffer::from_proto(1, message, None, cx).unwrap()
3015        });
3016        let multibuffer = cx.add_model(|cx| MultiBuffer::singleton(guest_buffer.clone(), cx));
3017        let snapshot = multibuffer.read(cx).snapshot(cx);
3018        assert_eq!(snapshot.text(), "a");
3019
3020        guest_buffer.update(cx, |buffer, cx| buffer.edit([(1..1, "b")], cx));
3021        let snapshot = multibuffer.read(cx).snapshot(cx);
3022        assert_eq!(snapshot.text(), "ab");
3023
3024        guest_buffer.update(cx, |buffer, cx| buffer.edit([(2..2, "c")], cx));
3025        let snapshot = multibuffer.read(cx).snapshot(cx);
3026        assert_eq!(snapshot.text(), "abc");
3027    }
3028
3029    #[gpui::test]
3030    fn test_excerpt_buffer(cx: &mut MutableAppContext) {
3031        let buffer_1 = cx.add_model(|cx| Buffer::new(0, sample_text(6, 6, 'a'), cx));
3032        let buffer_2 = cx.add_model(|cx| Buffer::new(0, sample_text(6, 6, 'g'), cx));
3033        let multibuffer = cx.add_model(|_| MultiBuffer::new(0));
3034
3035        let events = Rc::new(RefCell::new(Vec::<Event>::new()));
3036        multibuffer.update(cx, |_, cx| {
3037            let events = events.clone();
3038            cx.subscribe(&multibuffer, move |_, _, event, _| {
3039                events.borrow_mut().push(event.clone())
3040            })
3041            .detach();
3042        });
3043
3044        let subscription = multibuffer.update(cx, |multibuffer, cx| {
3045            let subscription = multibuffer.subscribe();
3046            multibuffer.push_excerpts(buffer_1.clone(), [Point::new(1, 2)..Point::new(2, 5)], cx);
3047            assert_eq!(
3048                subscription.consume().into_inner(),
3049                [Edit {
3050                    old: 0..0,
3051                    new: 0..10
3052                }]
3053            );
3054
3055            multibuffer.push_excerpts(buffer_1.clone(), [Point::new(3, 3)..Point::new(4, 4)], cx);
3056            multibuffer.push_excerpts(buffer_2.clone(), [Point::new(3, 1)..Point::new(3, 3)], cx);
3057            assert_eq!(
3058                subscription.consume().into_inner(),
3059                [Edit {
3060                    old: 10..10,
3061                    new: 10..22
3062                }]
3063            );
3064
3065            subscription
3066        });
3067
3068        // Adding excerpts emits an edited event.
3069        assert_eq!(
3070            events.borrow().as_slice(),
3071            &[Event::Edited, Event::Edited, Event::Edited]
3072        );
3073
3074        let snapshot = multibuffer.read(cx).snapshot(cx);
3075        assert_eq!(
3076            snapshot.text(),
3077            concat!(
3078                "bbbb\n",  // Preserve newlines
3079                "ccccc\n", //
3080                "ddd\n",   //
3081                "eeee\n",  //
3082                "jj"       //
3083            )
3084        );
3085        assert_eq!(
3086            snapshot.buffer_rows(0).collect::<Vec<_>>(),
3087            [Some(1), Some(2), Some(3), Some(4), Some(3)]
3088        );
3089        assert_eq!(
3090            snapshot.buffer_rows(2).collect::<Vec<_>>(),
3091            [Some(3), Some(4), Some(3)]
3092        );
3093        assert_eq!(snapshot.buffer_rows(4).collect::<Vec<_>>(), [Some(3)]);
3094        assert_eq!(snapshot.buffer_rows(5).collect::<Vec<_>>(), []);
3095
3096        assert_eq!(
3097            boundaries_in_range(Point::new(0, 0)..Point::new(4, 2), &snapshot),
3098            &[
3099                (0, "bbbb\nccccc".to_string(), true),
3100                (2, "ddd\neeee".to_string(), false),
3101                (4, "jj".to_string(), true),
3102            ]
3103        );
3104        assert_eq!(
3105            boundaries_in_range(Point::new(0, 0)..Point::new(2, 0), &snapshot),
3106            &[(0, "bbbb\nccccc".to_string(), true)]
3107        );
3108        assert_eq!(
3109            boundaries_in_range(Point::new(1, 0)..Point::new(1, 5), &snapshot),
3110            &[]
3111        );
3112        assert_eq!(
3113            boundaries_in_range(Point::new(1, 0)..Point::new(2, 0), &snapshot),
3114            &[]
3115        );
3116        assert_eq!(
3117            boundaries_in_range(Point::new(1, 0)..Point::new(4, 0), &snapshot),
3118            &[(2, "ddd\neeee".to_string(), false)]
3119        );
3120        assert_eq!(
3121            boundaries_in_range(Point::new(1, 0)..Point::new(4, 0), &snapshot),
3122            &[(2, "ddd\neeee".to_string(), false)]
3123        );
3124        assert_eq!(
3125            boundaries_in_range(Point::new(2, 0)..Point::new(3, 0), &snapshot),
3126            &[(2, "ddd\neeee".to_string(), false)]
3127        );
3128        assert_eq!(
3129            boundaries_in_range(Point::new(4, 0)..Point::new(4, 2), &snapshot),
3130            &[(4, "jj".to_string(), true)]
3131        );
3132        assert_eq!(
3133            boundaries_in_range(Point::new(4, 2)..Point::new(4, 2), &snapshot),
3134            &[]
3135        );
3136
3137        buffer_1.update(cx, |buffer, cx| {
3138            let text = "\n";
3139            buffer.edit(
3140                [
3141                    (Point::new(0, 0)..Point::new(0, 0), text),
3142                    (Point::new(2, 1)..Point::new(2, 3), text),
3143                ],
3144                cx,
3145            );
3146        });
3147
3148        let snapshot = multibuffer.read(cx).snapshot(cx);
3149        assert_eq!(
3150            snapshot.text(),
3151            concat!(
3152                "bbbb\n", // Preserve newlines
3153                "c\n",    //
3154                "cc\n",   //
3155                "ddd\n",  //
3156                "eeee\n", //
3157                "jj"      //
3158            )
3159        );
3160
3161        assert_eq!(
3162            subscription.consume().into_inner(),
3163            [Edit {
3164                old: 6..8,
3165                new: 6..7
3166            }]
3167        );
3168
3169        let snapshot = multibuffer.read(cx).snapshot(cx);
3170        assert_eq!(
3171            snapshot.clip_point(Point::new(0, 5), Bias::Left),
3172            Point::new(0, 4)
3173        );
3174        assert_eq!(
3175            snapshot.clip_point(Point::new(0, 5), Bias::Right),
3176            Point::new(0, 4)
3177        );
3178        assert_eq!(
3179            snapshot.clip_point(Point::new(5, 1), Bias::Right),
3180            Point::new(5, 1)
3181        );
3182        assert_eq!(
3183            snapshot.clip_point(Point::new(5, 2), Bias::Right),
3184            Point::new(5, 2)
3185        );
3186        assert_eq!(
3187            snapshot.clip_point(Point::new(5, 3), Bias::Right),
3188            Point::new(5, 2)
3189        );
3190
3191        let snapshot = multibuffer.update(cx, |multibuffer, cx| {
3192            let (buffer_2_excerpt_id, _) =
3193                multibuffer.excerpts_for_buffer(&buffer_2, cx)[0].clone();
3194            multibuffer.remove_excerpts(&[buffer_2_excerpt_id], cx);
3195            multibuffer.snapshot(cx)
3196        });
3197
3198        assert_eq!(
3199            snapshot.text(),
3200            concat!(
3201                "bbbb\n", // Preserve newlines
3202                "c\n",    //
3203                "cc\n",   //
3204                "ddd\n",  //
3205                "eeee",   //
3206            )
3207        );
3208
3209        fn boundaries_in_range(
3210            range: Range<Point>,
3211            snapshot: &MultiBufferSnapshot,
3212        ) -> Vec<(u32, String, bool)> {
3213            snapshot
3214                .excerpt_boundaries_in_range(range)
3215                .map(|boundary| {
3216                    (
3217                        boundary.row,
3218                        boundary
3219                            .buffer
3220                            .text_for_range(boundary.range)
3221                            .collect::<String>(),
3222                        boundary.starts_new_buffer,
3223                    )
3224                })
3225                .collect::<Vec<_>>()
3226        }
3227    }
3228
3229    #[gpui::test]
3230    fn test_excerpts_with_context_lines(cx: &mut MutableAppContext) {
3231        let buffer = cx.add_model(|cx| Buffer::new(0, sample_text(20, 3, 'a'), cx));
3232        let multibuffer = cx.add_model(|_| MultiBuffer::new(0));
3233        let anchor_ranges = multibuffer.update(cx, |multibuffer, cx| {
3234            multibuffer.push_excerpts_with_context_lines(
3235                buffer.clone(),
3236                vec![
3237                    Point::new(3, 2)..Point::new(4, 2),
3238                    Point::new(7, 1)..Point::new(7, 3),
3239                    Point::new(15, 0)..Point::new(15, 0),
3240                ],
3241                2,
3242                cx,
3243            )
3244        });
3245
3246        let snapshot = multibuffer.read(cx).snapshot(cx);
3247        assert_eq!(
3248            snapshot.text(),
3249            "bbb\nccc\nddd\neee\nfff\nggg\nhhh\niii\njjj\n\nnnn\nooo\nppp\nqqq\nrrr\n"
3250        );
3251
3252        assert_eq!(
3253            anchor_ranges
3254                .iter()
3255                .map(|range| range.to_point(&snapshot))
3256                .collect::<Vec<_>>(),
3257            vec![
3258                Point::new(2, 2)..Point::new(3, 2),
3259                Point::new(6, 1)..Point::new(6, 3),
3260                Point::new(12, 0)..Point::new(12, 0)
3261            ]
3262        );
3263    }
3264
3265    #[gpui::test]
3266    fn test_empty_excerpt_buffer(cx: &mut MutableAppContext) {
3267        let multibuffer = cx.add_model(|_| MultiBuffer::new(0));
3268
3269        let snapshot = multibuffer.read(cx).snapshot(cx);
3270        assert_eq!(snapshot.text(), "");
3271        assert_eq!(snapshot.buffer_rows(0).collect::<Vec<_>>(), &[Some(0)]);
3272        assert_eq!(snapshot.buffer_rows(1).collect::<Vec<_>>(), &[]);
3273    }
3274
3275    #[gpui::test]
3276    fn test_singleton_multibuffer_anchors(cx: &mut MutableAppContext) {
3277        let buffer = cx.add_model(|cx| Buffer::new(0, "abcd", cx));
3278        let multibuffer = cx.add_model(|cx| MultiBuffer::singleton(buffer.clone(), cx));
3279        let old_snapshot = multibuffer.read(cx).snapshot(cx);
3280        buffer.update(cx, |buffer, cx| {
3281            buffer.edit([(0..0, "X")], cx);
3282            buffer.edit([(5..5, "Y")], cx);
3283        });
3284        let new_snapshot = multibuffer.read(cx).snapshot(cx);
3285
3286        assert_eq!(old_snapshot.text(), "abcd");
3287        assert_eq!(new_snapshot.text(), "XabcdY");
3288
3289        assert_eq!(old_snapshot.anchor_before(0).to_offset(&new_snapshot), 0);
3290        assert_eq!(old_snapshot.anchor_after(0).to_offset(&new_snapshot), 1);
3291        assert_eq!(old_snapshot.anchor_before(4).to_offset(&new_snapshot), 5);
3292        assert_eq!(old_snapshot.anchor_after(4).to_offset(&new_snapshot), 6);
3293    }
3294
3295    #[gpui::test]
3296    fn test_multibuffer_anchors(cx: &mut MutableAppContext) {
3297        let buffer_1 = cx.add_model(|cx| Buffer::new(0, "abcd", cx));
3298        let buffer_2 = cx.add_model(|cx| Buffer::new(0, "efghi", cx));
3299        let multibuffer = cx.add_model(|cx| {
3300            let mut multibuffer = MultiBuffer::new(0);
3301            multibuffer.push_excerpts(buffer_1.clone(), [0..4], cx);
3302            multibuffer.push_excerpts(buffer_2.clone(), [0..5], cx);
3303            multibuffer
3304        });
3305        let old_snapshot = multibuffer.read(cx).snapshot(cx);
3306
3307        assert_eq!(old_snapshot.anchor_before(0).to_offset(&old_snapshot), 0);
3308        assert_eq!(old_snapshot.anchor_after(0).to_offset(&old_snapshot), 0);
3309        assert_eq!(Anchor::min().to_offset(&old_snapshot), 0);
3310        assert_eq!(Anchor::min().to_offset(&old_snapshot), 0);
3311        assert_eq!(Anchor::max().to_offset(&old_snapshot), 10);
3312        assert_eq!(Anchor::max().to_offset(&old_snapshot), 10);
3313
3314        buffer_1.update(cx, |buffer, cx| {
3315            buffer.edit([(0..0, "W")], cx);
3316            buffer.edit([(5..5, "X")], cx);
3317        });
3318        buffer_2.update(cx, |buffer, cx| {
3319            buffer.edit([(0..0, "Y")], cx);
3320            buffer.edit([(6..0, "Z")], cx);
3321        });
3322        let new_snapshot = multibuffer.read(cx).snapshot(cx);
3323
3324        assert_eq!(old_snapshot.text(), "abcd\nefghi");
3325        assert_eq!(new_snapshot.text(), "WabcdX\nYefghiZ");
3326
3327        assert_eq!(old_snapshot.anchor_before(0).to_offset(&new_snapshot), 0);
3328        assert_eq!(old_snapshot.anchor_after(0).to_offset(&new_snapshot), 1);
3329        assert_eq!(old_snapshot.anchor_before(1).to_offset(&new_snapshot), 2);
3330        assert_eq!(old_snapshot.anchor_after(1).to_offset(&new_snapshot), 2);
3331        assert_eq!(old_snapshot.anchor_before(2).to_offset(&new_snapshot), 3);
3332        assert_eq!(old_snapshot.anchor_after(2).to_offset(&new_snapshot), 3);
3333        assert_eq!(old_snapshot.anchor_before(5).to_offset(&new_snapshot), 7);
3334        assert_eq!(old_snapshot.anchor_after(5).to_offset(&new_snapshot), 8);
3335        assert_eq!(old_snapshot.anchor_before(10).to_offset(&new_snapshot), 13);
3336        assert_eq!(old_snapshot.anchor_after(10).to_offset(&new_snapshot), 14);
3337    }
3338
3339    #[gpui::test]
3340    fn test_multibuffer_resolving_anchors_after_replacing_their_excerpts(
3341        cx: &mut MutableAppContext,
3342    ) {
3343        let buffer_1 = cx.add_model(|cx| Buffer::new(0, "abcd", cx));
3344        let buffer_2 = cx.add_model(|cx| Buffer::new(0, "ABCDEFGHIJKLMNOP", cx));
3345        let multibuffer = cx.add_model(|_| MultiBuffer::new(0));
3346
3347        // Create an insertion id in buffer 1 that doesn't exist in buffer 2.
3348        // Add an excerpt from buffer 1 that spans this new insertion.
3349        buffer_1.update(cx, |buffer, cx| buffer.edit([(4..4, "123")], cx));
3350        let excerpt_id_1 = multibuffer.update(cx, |multibuffer, cx| {
3351            multibuffer
3352                .push_excerpts(buffer_1.clone(), [0..7], cx)
3353                .pop()
3354                .unwrap()
3355        });
3356
3357        let snapshot_1 = multibuffer.read(cx).snapshot(cx);
3358        assert_eq!(snapshot_1.text(), "abcd123");
3359
3360        // Replace the buffer 1 excerpt with new excerpts from buffer 2.
3361        let (excerpt_id_2, excerpt_id_3) = multibuffer.update(cx, |multibuffer, cx| {
3362            multibuffer.remove_excerpts([&excerpt_id_1], cx);
3363            let mut ids = multibuffer
3364                .push_excerpts(buffer_2.clone(), [0..4, 6..10, 12..16], cx)
3365                .into_iter();
3366            (ids.next().unwrap(), ids.next().unwrap())
3367        });
3368        let snapshot_2 = multibuffer.read(cx).snapshot(cx);
3369        assert_eq!(snapshot_2.text(), "ABCD\nGHIJ\nMNOP");
3370
3371        // The old excerpt id doesn't get reused.
3372        assert_ne!(excerpt_id_2, excerpt_id_1);
3373
3374        // Resolve some anchors from the previous snapshot in the new snapshot.
3375        // Although there is still an excerpt with the same id, it is for
3376        // a different buffer, so we don't attempt to resolve the old text
3377        // anchor in the new buffer.
3378        assert_eq!(
3379            snapshot_2.summary_for_anchor::<usize>(&snapshot_1.anchor_before(2)),
3380            0
3381        );
3382        assert_eq!(
3383            snapshot_2.summaries_for_anchors::<usize, _>(&[
3384                snapshot_1.anchor_before(2),
3385                snapshot_1.anchor_after(3)
3386            ]),
3387            vec![0, 0]
3388        );
3389        let refresh =
3390            snapshot_2.refresh_anchors(&[snapshot_1.anchor_before(2), snapshot_1.anchor_after(3)]);
3391        assert_eq!(
3392            refresh,
3393            &[
3394                (0, snapshot_2.anchor_before(0), false),
3395                (1, snapshot_2.anchor_after(0), false),
3396            ]
3397        );
3398
3399        // Replace the middle excerpt with a smaller excerpt in buffer 2,
3400        // that intersects the old excerpt.
3401        let excerpt_id_5 = multibuffer.update(cx, |multibuffer, cx| {
3402            multibuffer.remove_excerpts([&excerpt_id_3], cx);
3403            multibuffer
3404                .insert_excerpts_after(&excerpt_id_3, buffer_2.clone(), [5..8], cx)
3405                .pop()
3406                .unwrap()
3407        });
3408
3409        let snapshot_3 = multibuffer.read(cx).snapshot(cx);
3410        assert_eq!(snapshot_3.text(), "ABCD\nFGH\nMNOP");
3411        assert_ne!(excerpt_id_5, excerpt_id_3);
3412
3413        // Resolve some anchors from the previous snapshot in the new snapshot.
3414        // The anchor in the middle excerpt snaps to the beginning of the
3415        // excerpt, since it is not
3416        let anchors = [
3417            snapshot_2.anchor_before(0),
3418            snapshot_2.anchor_after(2),
3419            snapshot_2.anchor_after(6),
3420            snapshot_2.anchor_after(14),
3421        ];
3422        assert_eq!(
3423            snapshot_3.summaries_for_anchors::<usize, _>(&anchors),
3424            &[0, 2, 5, 13]
3425        );
3426
3427        let new_anchors = snapshot_3.refresh_anchors(&anchors);
3428        assert_eq!(
3429            new_anchors.iter().map(|a| (a.0, a.2)).collect::<Vec<_>>(),
3430            &[(0, true), (1, true), (2, true), (3, true)]
3431        );
3432        assert_eq!(
3433            snapshot_3.summaries_for_anchors::<usize, _>(new_anchors.iter().map(|a| &a.1)),
3434            &[0, 2, 7, 13]
3435        );
3436    }
3437
3438    #[gpui::test(iterations = 100)]
3439    fn test_random_multibuffer(cx: &mut MutableAppContext, mut rng: StdRng) {
3440        let operations = env::var("OPERATIONS")
3441            .map(|i| i.parse().expect("invalid `OPERATIONS` variable"))
3442            .unwrap_or(10);
3443
3444        let mut buffers: Vec<ModelHandle<Buffer>> = Vec::new();
3445        let multibuffer = cx.add_model(|_| MultiBuffer::new(0));
3446        let mut excerpt_ids = Vec::new();
3447        let mut expected_excerpts = Vec::<(ModelHandle<Buffer>, Range<text::Anchor>)>::new();
3448        let mut anchors = Vec::new();
3449        let mut old_versions = Vec::new();
3450
3451        for _ in 0..operations {
3452            match rng.gen_range(0..100) {
3453                0..=19 if !buffers.is_empty() => {
3454                    let buffer = buffers.choose(&mut rng).unwrap();
3455                    buffer.update(cx, |buf, cx| buf.randomly_edit(&mut rng, 5, cx));
3456                }
3457                20..=29 if !expected_excerpts.is_empty() => {
3458                    let mut ids_to_remove = vec![];
3459                    for _ in 0..rng.gen_range(1..=3) {
3460                        if expected_excerpts.is_empty() {
3461                            break;
3462                        }
3463
3464                        let ix = rng.gen_range(0..expected_excerpts.len());
3465                        ids_to_remove.push(excerpt_ids.remove(ix));
3466                        let (buffer, range) = expected_excerpts.remove(ix);
3467                        let buffer = buffer.read(cx);
3468                        log::info!(
3469                            "Removing excerpt {}: {:?}",
3470                            ix,
3471                            buffer
3472                                .text_for_range(range.to_offset(&buffer))
3473                                .collect::<String>(),
3474                        );
3475                    }
3476                    ids_to_remove.sort_unstable();
3477                    multibuffer.update(cx, |multibuffer, cx| {
3478                        multibuffer.remove_excerpts(&ids_to_remove, cx)
3479                    });
3480                }
3481                30..=39 if !expected_excerpts.is_empty() => {
3482                    let multibuffer = multibuffer.read(cx).read(cx);
3483                    let offset =
3484                        multibuffer.clip_offset(rng.gen_range(0..=multibuffer.len()), Bias::Left);
3485                    let bias = if rng.gen() { Bias::Left } else { Bias::Right };
3486                    log::info!("Creating anchor at {} with bias {:?}", offset, bias);
3487                    anchors.push(multibuffer.anchor_at(offset, bias));
3488                    anchors.sort_by(|a, b| a.cmp(&b, &multibuffer));
3489                }
3490                40..=44 if !anchors.is_empty() => {
3491                    let multibuffer = multibuffer.read(cx).read(cx);
3492                    let prev_len = anchors.len();
3493                    anchors = multibuffer
3494                        .refresh_anchors(&anchors)
3495                        .into_iter()
3496                        .map(|a| a.1)
3497                        .collect();
3498
3499                    // Ensure the newly-refreshed anchors point to a valid excerpt and don't
3500                    // overshoot its boundaries.
3501                    assert_eq!(anchors.len(), prev_len);
3502                    let mut cursor = multibuffer.excerpts.cursor::<Option<&ExcerptId>>();
3503                    for anchor in &anchors {
3504                        if anchor.excerpt_id == ExcerptId::min()
3505                            || anchor.excerpt_id == ExcerptId::max()
3506                        {
3507                            continue;
3508                        }
3509
3510                        cursor.seek_forward(&Some(&anchor.excerpt_id), Bias::Left, &());
3511                        let excerpt = cursor.item().unwrap();
3512                        assert_eq!(excerpt.id, anchor.excerpt_id);
3513                        assert!(excerpt.contains(anchor));
3514                    }
3515                }
3516                _ => {
3517                    let buffer_handle = if buffers.is_empty() || rng.gen_bool(0.4) {
3518                        let base_text = RandomCharIter::new(&mut rng).take(10).collect::<String>();
3519                        buffers.push(cx.add_model(|cx| Buffer::new(0, base_text, cx)));
3520                        buffers.last().unwrap()
3521                    } else {
3522                        buffers.choose(&mut rng).unwrap()
3523                    };
3524
3525                    let buffer = buffer_handle.read(cx);
3526                    let end_ix = buffer.clip_offset(rng.gen_range(0..=buffer.len()), Bias::Right);
3527                    let start_ix = buffer.clip_offset(rng.gen_range(0..=end_ix), Bias::Left);
3528                    let anchor_range = buffer.anchor_before(start_ix)..buffer.anchor_after(end_ix);
3529                    let prev_excerpt_ix = rng.gen_range(0..=expected_excerpts.len());
3530                    let prev_excerpt_id = excerpt_ids
3531                        .get(prev_excerpt_ix)
3532                        .cloned()
3533                        .unwrap_or(ExcerptId::max());
3534                    let excerpt_ix = (prev_excerpt_ix + 1).min(expected_excerpts.len());
3535
3536                    log::info!(
3537                        "Inserting excerpt at {} of {} for buffer {}: {:?}[{:?}] = {:?}",
3538                        excerpt_ix,
3539                        expected_excerpts.len(),
3540                        buffer_handle.id(),
3541                        buffer.text(),
3542                        start_ix..end_ix,
3543                        &buffer.text()[start_ix..end_ix]
3544                    );
3545
3546                    let excerpt_id = multibuffer.update(cx, |multibuffer, cx| {
3547                        multibuffer
3548                            .insert_excerpts_after(
3549                                &prev_excerpt_id,
3550                                buffer_handle.clone(),
3551                                [start_ix..end_ix],
3552                                cx,
3553                            )
3554                            .pop()
3555                            .unwrap()
3556                    });
3557
3558                    excerpt_ids.insert(excerpt_ix, excerpt_id);
3559                    expected_excerpts.insert(excerpt_ix, (buffer_handle.clone(), anchor_range));
3560                }
3561            }
3562
3563            if rng.gen_bool(0.3) {
3564                multibuffer.update(cx, |multibuffer, cx| {
3565                    old_versions.push((multibuffer.snapshot(cx), multibuffer.subscribe()));
3566                })
3567            }
3568
3569            let snapshot = multibuffer.read(cx).snapshot(cx);
3570
3571            let mut excerpt_starts = Vec::new();
3572            let mut expected_text = String::new();
3573            let mut expected_buffer_rows = Vec::new();
3574            for (buffer, range) in &expected_excerpts {
3575                let buffer = buffer.read(cx);
3576                let buffer_range = range.to_offset(buffer);
3577
3578                excerpt_starts.push(TextSummary::from(expected_text.as_str()));
3579                expected_text.extend(buffer.text_for_range(buffer_range.clone()));
3580                expected_text.push('\n');
3581
3582                let buffer_row_range = buffer.offset_to_point(buffer_range.start).row
3583                    ..=buffer.offset_to_point(buffer_range.end).row;
3584                for row in buffer_row_range {
3585                    expected_buffer_rows.push(Some(row));
3586                }
3587            }
3588            // Remove final trailing newline.
3589            if !expected_excerpts.is_empty() {
3590                expected_text.pop();
3591            }
3592
3593            // Always report one buffer row
3594            if expected_buffer_rows.is_empty() {
3595                expected_buffer_rows.push(Some(0));
3596            }
3597
3598            assert_eq!(snapshot.text(), expected_text);
3599            log::info!("MultiBuffer text: {:?}", expected_text);
3600
3601            assert_eq!(
3602                snapshot.buffer_rows(0).collect::<Vec<_>>(),
3603                expected_buffer_rows,
3604            );
3605
3606            for _ in 0..5 {
3607                let start_row = rng.gen_range(0..=expected_buffer_rows.len());
3608                assert_eq!(
3609                    snapshot.buffer_rows(start_row as u32).collect::<Vec<_>>(),
3610                    &expected_buffer_rows[start_row..],
3611                    "buffer_rows({})",
3612                    start_row
3613                );
3614            }
3615
3616            assert_eq!(
3617                snapshot.max_buffer_row(),
3618                expected_buffer_rows
3619                    .into_iter()
3620                    .filter_map(|r| r)
3621                    .max()
3622                    .unwrap()
3623            );
3624
3625            let mut excerpt_starts = excerpt_starts.into_iter();
3626            for (buffer, range) in &expected_excerpts {
3627                let buffer_id = buffer.id();
3628                let buffer = buffer.read(cx);
3629                let buffer_range = range.to_offset(buffer);
3630                let buffer_start_point = buffer.offset_to_point(buffer_range.start);
3631                let buffer_start_point_utf16 =
3632                    buffer.text_summary_for_range::<PointUtf16, _>(0..buffer_range.start);
3633
3634                let excerpt_start = excerpt_starts.next().unwrap();
3635                let mut offset = excerpt_start.bytes;
3636                let mut buffer_offset = buffer_range.start;
3637                let mut point = excerpt_start.lines;
3638                let mut buffer_point = buffer_start_point;
3639                let mut point_utf16 = excerpt_start.lines_utf16;
3640                let mut buffer_point_utf16 = buffer_start_point_utf16;
3641                for ch in buffer
3642                    .snapshot()
3643                    .chunks(buffer_range.clone(), false)
3644                    .flat_map(|c| c.text.chars())
3645                {
3646                    for _ in 0..ch.len_utf8() {
3647                        let left_offset = snapshot.clip_offset(offset, Bias::Left);
3648                        let right_offset = snapshot.clip_offset(offset, Bias::Right);
3649                        let buffer_left_offset = buffer.clip_offset(buffer_offset, Bias::Left);
3650                        let buffer_right_offset = buffer.clip_offset(buffer_offset, Bias::Right);
3651                        assert_eq!(
3652                            left_offset,
3653                            excerpt_start.bytes + (buffer_left_offset - buffer_range.start),
3654                            "clip_offset({:?}, Left). buffer: {:?}, buffer offset: {:?}",
3655                            offset,
3656                            buffer_id,
3657                            buffer_offset,
3658                        );
3659                        assert_eq!(
3660                            right_offset,
3661                            excerpt_start.bytes + (buffer_right_offset - buffer_range.start),
3662                            "clip_offset({:?}, Right). buffer: {:?}, buffer offset: {:?}",
3663                            offset,
3664                            buffer_id,
3665                            buffer_offset,
3666                        );
3667
3668                        let left_point = snapshot.clip_point(point, Bias::Left);
3669                        let right_point = snapshot.clip_point(point, Bias::Right);
3670                        let buffer_left_point = buffer.clip_point(buffer_point, Bias::Left);
3671                        let buffer_right_point = buffer.clip_point(buffer_point, Bias::Right);
3672                        assert_eq!(
3673                            left_point,
3674                            excerpt_start.lines + (buffer_left_point - buffer_start_point),
3675                            "clip_point({:?}, Left). buffer: {:?}, buffer point: {:?}",
3676                            point,
3677                            buffer_id,
3678                            buffer_point,
3679                        );
3680                        assert_eq!(
3681                            right_point,
3682                            excerpt_start.lines + (buffer_right_point - buffer_start_point),
3683                            "clip_point({:?}, Right). buffer: {:?}, buffer point: {:?}",
3684                            point,
3685                            buffer_id,
3686                            buffer_point,
3687                        );
3688
3689                        assert_eq!(
3690                            snapshot.point_to_offset(left_point),
3691                            left_offset,
3692                            "point_to_offset({:?})",
3693                            left_point,
3694                        );
3695                        assert_eq!(
3696                            snapshot.offset_to_point(left_offset),
3697                            left_point,
3698                            "offset_to_point({:?})",
3699                            left_offset,
3700                        );
3701
3702                        offset += 1;
3703                        buffer_offset += 1;
3704                        if ch == '\n' {
3705                            point += Point::new(1, 0);
3706                            buffer_point += Point::new(1, 0);
3707                        } else {
3708                            point += Point::new(0, 1);
3709                            buffer_point += Point::new(0, 1);
3710                        }
3711                    }
3712
3713                    for _ in 0..ch.len_utf16() {
3714                        let left_point_utf16 = snapshot.clip_point_utf16(point_utf16, Bias::Left);
3715                        let right_point_utf16 = snapshot.clip_point_utf16(point_utf16, Bias::Right);
3716                        let buffer_left_point_utf16 =
3717                            buffer.clip_point_utf16(buffer_point_utf16, Bias::Left);
3718                        let buffer_right_point_utf16 =
3719                            buffer.clip_point_utf16(buffer_point_utf16, Bias::Right);
3720                        assert_eq!(
3721                            left_point_utf16,
3722                            excerpt_start.lines_utf16
3723                                + (buffer_left_point_utf16 - buffer_start_point_utf16),
3724                            "clip_point_utf16({:?}, Left). buffer: {:?}, buffer point_utf16: {:?}",
3725                            point_utf16,
3726                            buffer_id,
3727                            buffer_point_utf16,
3728                        );
3729                        assert_eq!(
3730                            right_point_utf16,
3731                            excerpt_start.lines_utf16
3732                                + (buffer_right_point_utf16 - buffer_start_point_utf16),
3733                            "clip_point_utf16({:?}, Right). buffer: {:?}, buffer point_utf16: {:?}",
3734                            point_utf16,
3735                            buffer_id,
3736                            buffer_point_utf16,
3737                        );
3738
3739                        if ch == '\n' {
3740                            point_utf16 += PointUtf16::new(1, 0);
3741                            buffer_point_utf16 += PointUtf16::new(1, 0);
3742                        } else {
3743                            point_utf16 += PointUtf16::new(0, 1);
3744                            buffer_point_utf16 += PointUtf16::new(0, 1);
3745                        }
3746                    }
3747                }
3748            }
3749
3750            for (row, line) in expected_text.split('\n').enumerate() {
3751                assert_eq!(
3752                    snapshot.line_len(row as u32),
3753                    line.len() as u32,
3754                    "line_len({}).",
3755                    row
3756                );
3757            }
3758
3759            let text_rope = Rope::from(expected_text.as_str());
3760            for _ in 0..10 {
3761                let end_ix = text_rope.clip_offset(rng.gen_range(0..=text_rope.len()), Bias::Right);
3762                let start_ix = text_rope.clip_offset(rng.gen_range(0..=end_ix), Bias::Left);
3763
3764                let text_for_range = snapshot
3765                    .text_for_range(start_ix..end_ix)
3766                    .collect::<String>();
3767                assert_eq!(
3768                    text_for_range,
3769                    &expected_text[start_ix..end_ix],
3770                    "incorrect text for range {:?}",
3771                    start_ix..end_ix
3772                );
3773
3774                let excerpted_buffer_ranges = multibuffer
3775                    .read(cx)
3776                    .range_to_buffer_ranges(start_ix..end_ix, cx);
3777                let excerpted_buffers_text = excerpted_buffer_ranges
3778                    .into_iter()
3779                    .map(|(buffer, buffer_range)| {
3780                        buffer
3781                            .read(cx)
3782                            .text_for_range(buffer_range)
3783                            .collect::<String>()
3784                    })
3785                    .collect::<Vec<_>>()
3786                    .join("\n");
3787                assert_eq!(excerpted_buffers_text, text_for_range);
3788
3789                let expected_summary = TextSummary::from(&expected_text[start_ix..end_ix]);
3790                assert_eq!(
3791                    snapshot.text_summary_for_range::<TextSummary, _>(start_ix..end_ix),
3792                    expected_summary,
3793                    "incorrect summary for range {:?}",
3794                    start_ix..end_ix
3795                );
3796            }
3797
3798            // Anchor resolution
3799            let summaries = snapshot.summaries_for_anchors::<usize, _>(&anchors);
3800            assert_eq!(anchors.len(), summaries.len());
3801            for (anchor, resolved_offset) in anchors.iter().zip(summaries) {
3802                assert!(resolved_offset <= snapshot.len());
3803                assert_eq!(
3804                    snapshot.summary_for_anchor::<usize>(anchor),
3805                    resolved_offset
3806                );
3807            }
3808
3809            for _ in 0..10 {
3810                let end_ix = text_rope.clip_offset(rng.gen_range(0..=text_rope.len()), Bias::Right);
3811                assert_eq!(
3812                    snapshot.reversed_chars_at(end_ix).collect::<String>(),
3813                    expected_text[..end_ix].chars().rev().collect::<String>(),
3814                );
3815            }
3816
3817            for _ in 0..10 {
3818                let end_ix = rng.gen_range(0..=text_rope.len());
3819                let start_ix = rng.gen_range(0..=end_ix);
3820                assert_eq!(
3821                    snapshot
3822                        .bytes_in_range(start_ix..end_ix)
3823                        .flatten()
3824                        .copied()
3825                        .collect::<Vec<_>>(),
3826                    expected_text.as_bytes()[start_ix..end_ix].to_vec(),
3827                    "bytes_in_range({:?})",
3828                    start_ix..end_ix,
3829                );
3830            }
3831        }
3832
3833        let snapshot = multibuffer.read(cx).snapshot(cx);
3834        for (old_snapshot, subscription) in old_versions {
3835            let edits = subscription.consume().into_inner();
3836
3837            log::info!(
3838                "applying subscription edits to old text: {:?}: {:?}",
3839                old_snapshot.text(),
3840                edits,
3841            );
3842
3843            let mut text = old_snapshot.text();
3844            for edit in edits {
3845                let new_text: String = snapshot.text_for_range(edit.new.clone()).collect();
3846                text.replace_range(edit.new.start..edit.new.start + edit.old.len(), &new_text);
3847            }
3848            assert_eq!(text.to_string(), snapshot.text());
3849        }
3850    }
3851
3852    #[gpui::test]
3853    fn test_history(cx: &mut MutableAppContext) {
3854        cx.set_global(Settings::test(cx));
3855        let buffer_1 = cx.add_model(|cx| Buffer::new(0, "1234", cx));
3856        let buffer_2 = cx.add_model(|cx| Buffer::new(0, "5678", cx));
3857        let multibuffer = cx.add_model(|_| MultiBuffer::new(0));
3858        let group_interval = multibuffer.read(cx).history.group_interval;
3859        multibuffer.update(cx, |multibuffer, cx| {
3860            multibuffer.push_excerpts(buffer_1.clone(), [0..buffer_1.read(cx).len()], cx);
3861            multibuffer.push_excerpts(buffer_2.clone(), [0..buffer_2.read(cx).len()], cx);
3862        });
3863
3864        let mut now = Instant::now();
3865
3866        multibuffer.update(cx, |multibuffer, cx| {
3867            multibuffer.start_transaction_at(now, cx);
3868            multibuffer.edit(
3869                [
3870                    (Point::new(0, 0)..Point::new(0, 0), "A"),
3871                    (Point::new(1, 0)..Point::new(1, 0), "A"),
3872                ],
3873                cx,
3874            );
3875            multibuffer.edit(
3876                [
3877                    (Point::new(0, 1)..Point::new(0, 1), "B"),
3878                    (Point::new(1, 1)..Point::new(1, 1), "B"),
3879                ],
3880                cx,
3881            );
3882            multibuffer.end_transaction_at(now, cx);
3883            assert_eq!(multibuffer.read(cx).text(), "AB1234\nAB5678");
3884
3885            // Edit buffer 1 through the multibuffer
3886            now += 2 * group_interval;
3887            multibuffer.start_transaction_at(now, cx);
3888            multibuffer.edit([(2..2, "C")], cx);
3889            multibuffer.end_transaction_at(now, cx);
3890            assert_eq!(multibuffer.read(cx).text(), "ABC1234\nAB5678");
3891
3892            // Edit buffer 1 independently
3893            buffer_1.update(cx, |buffer_1, cx| {
3894                buffer_1.start_transaction_at(now);
3895                buffer_1.edit([(3..3, "D")], cx);
3896                buffer_1.end_transaction_at(now, cx);
3897
3898                now += 2 * group_interval;
3899                buffer_1.start_transaction_at(now);
3900                buffer_1.edit([(4..4, "E")], cx);
3901                buffer_1.end_transaction_at(now, cx);
3902            });
3903            assert_eq!(multibuffer.read(cx).text(), "ABCDE1234\nAB5678");
3904
3905            // An undo in the multibuffer undoes the multibuffer transaction
3906            // and also any individual buffer edits that have occured since
3907            // that transaction.
3908            multibuffer.undo(cx);
3909            assert_eq!(multibuffer.read(cx).text(), "AB1234\nAB5678");
3910
3911            multibuffer.undo(cx);
3912            assert_eq!(multibuffer.read(cx).text(), "1234\n5678");
3913
3914            multibuffer.redo(cx);
3915            assert_eq!(multibuffer.read(cx).text(), "AB1234\nAB5678");
3916
3917            multibuffer.redo(cx);
3918            assert_eq!(multibuffer.read(cx).text(), "ABCDE1234\nAB5678");
3919
3920            // Undo buffer 2 independently.
3921            buffer_2.update(cx, |buffer_2, cx| buffer_2.undo(cx));
3922            assert_eq!(multibuffer.read(cx).text(), "ABCDE1234\n5678");
3923
3924            // An undo in the multibuffer undoes the components of the
3925            // the last multibuffer transaction that are not already undone.
3926            multibuffer.undo(cx);
3927            assert_eq!(multibuffer.read(cx).text(), "AB1234\n5678");
3928
3929            multibuffer.undo(cx);
3930            assert_eq!(multibuffer.read(cx).text(), "1234\n5678");
3931
3932            multibuffer.redo(cx);
3933            assert_eq!(multibuffer.read(cx).text(), "AB1234\nAB5678");
3934
3935            buffer_1.update(cx, |buffer_1, cx| buffer_1.redo(cx));
3936            assert_eq!(multibuffer.read(cx).text(), "ABCD1234\nAB5678");
3937
3938            multibuffer.undo(cx);
3939            assert_eq!(multibuffer.read(cx).text(), "1234\n5678");
3940        });
3941    }
3942}