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