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