multi_buffer.rs

   1mod anchor;
   2
   3pub use anchor::{Anchor, AnchorRangeExt};
   4use anyhow::Result;
   5use clock::ReplicaId;
   6use collections::{HashMap, HashSet};
   7use gpui::{AppContext, Entity, ModelContext, ModelHandle, Task};
   8use language::{
   9    Buffer, BufferChunks, BufferSnapshot, Chunk, DiagnosticEntry, Event, File, Language, Selection,
  10    ToOffset as _, ToPoint as _, TransactionId,
  11};
  12use std::{
  13    cell::{Ref, RefCell},
  14    cmp, fmt, io,
  15    iter::{self, FromIterator},
  16    ops::{Range, Sub},
  17    str,
  18    sync::Arc,
  19    time::{Duration, Instant},
  20};
  21use sum_tree::{Bias, Cursor, SumTree};
  22use text::{
  23    locator::Locator,
  24    rope::TextDimension,
  25    subscription::{Subscription, Topic},
  26    AnchorRangeExt as _, Edit, Point, PointUtf16, TextSummary,
  27};
  28use theme::SyntaxTheme;
  29use util::post_inc;
  30
  31const NEWLINES: &'static [u8] = &[b'\n'; u8::MAX as usize];
  32
  33pub type ExcerptId = Locator;
  34
  35pub struct MultiBuffer {
  36    snapshot: RefCell<MultiBufferSnapshot>,
  37    buffers: RefCell<HashMap<usize, BufferState>>,
  38    subscriptions: Topic,
  39    singleton: bool,
  40    replica_id: ReplicaId,
  41    history: History,
  42}
  43
  44struct History {
  45    next_transaction_id: usize,
  46    undo_stack: Vec<Transaction>,
  47    redo_stack: Vec<Transaction>,
  48    transaction_depth: usize,
  49    group_interval: Duration,
  50}
  51
  52struct Transaction {
  53    id: usize,
  54    buffer_transactions: HashSet<(usize, text::TransactionId)>,
  55    first_edit_at: Instant,
  56    last_edit_at: Instant,
  57}
  58
  59pub trait ToOffset: 'static + fmt::Debug {
  60    fn to_offset(&self, snapshot: &MultiBufferSnapshot) -> usize;
  61}
  62
  63pub trait ToPoint: 'static + fmt::Debug {
  64    fn to_point(&self, snapshot: &MultiBufferSnapshot) -> Point;
  65}
  66
  67pub trait FromAnchor: 'static {
  68    fn from_anchor(anchor: &Anchor, snapshot: &MultiBufferSnapshot) -> Self;
  69}
  70
  71struct BufferState {
  72    buffer: ModelHandle<Buffer>,
  73    last_version: clock::Global,
  74    last_parse_count: usize,
  75    last_diagnostics_update_count: usize,
  76    excerpts: Vec<ExcerptId>,
  77    _subscriptions: [gpui::Subscription; 2],
  78}
  79
  80#[derive(Clone, Default)]
  81pub struct MultiBufferSnapshot {
  82    excerpts: SumTree<Excerpt>,
  83    parse_count: usize,
  84    diagnostics_update_count: usize,
  85    is_dirty: bool,
  86    has_conflict: bool,
  87}
  88
  89pub struct ExcerptProperties<'a, T> {
  90    pub buffer: &'a ModelHandle<Buffer>,
  91    pub range: Range<T>,
  92}
  93
  94#[derive(Clone)]
  95struct Excerpt {
  96    id: ExcerptId,
  97    buffer_id: usize,
  98    buffer: BufferSnapshot,
  99    range: Range<text::Anchor>,
 100    max_buffer_row: u32,
 101    text_summary: TextSummary,
 102    has_trailing_newline: bool,
 103}
 104
 105#[derive(Clone, Debug, Default)]
 106struct ExcerptSummary {
 107    excerpt_id: ExcerptId,
 108    max_buffer_row: u32,
 109    text: TextSummary,
 110}
 111
 112pub struct MultiBufferRows<'a> {
 113    buffer_row_range: Range<u32>,
 114    excerpts: Cursor<'a, Excerpt, Point>,
 115}
 116
 117pub struct MultiBufferChunks<'a> {
 118    range: Range<usize>,
 119    excerpts: Cursor<'a, Excerpt, usize>,
 120    excerpt_chunks: Option<ExcerptChunks<'a>>,
 121    theme: Option<&'a SyntaxTheme>,
 122}
 123
 124pub struct MultiBufferBytes<'a> {
 125    range: Range<usize>,
 126    excerpts: Cursor<'a, Excerpt, usize>,
 127    excerpt_bytes: Option<ExcerptBytes<'a>>,
 128    chunk: &'a [u8],
 129}
 130
 131struct ExcerptChunks<'a> {
 132    content_chunks: BufferChunks<'a>,
 133    footer_height: usize,
 134}
 135
 136struct ExcerptBytes<'a> {
 137    content_bytes: language::rope::Bytes<'a>,
 138    footer_height: usize,
 139}
 140
 141impl MultiBuffer {
 142    pub fn new(replica_id: ReplicaId) -> Self {
 143        Self {
 144            snapshot: Default::default(),
 145            buffers: Default::default(),
 146            subscriptions: Default::default(),
 147            singleton: false,
 148            replica_id,
 149            history: History {
 150                next_transaction_id: Default::default(),
 151                undo_stack: Default::default(),
 152                redo_stack: Default::default(),
 153                transaction_depth: 0,
 154                group_interval: Duration::from_millis(300),
 155            },
 156        }
 157    }
 158
 159    pub fn singleton(buffer: ModelHandle<Buffer>, cx: &mut ModelContext<Self>) -> Self {
 160        let mut this = Self::new(buffer.read(cx).replica_id());
 161        this.singleton = true;
 162        this.push_excerpt(
 163            ExcerptProperties {
 164                buffer: &buffer,
 165                range: text::Anchor::min()..text::Anchor::max(),
 166            },
 167            cx,
 168        );
 169        this
 170    }
 171
 172    #[cfg(any(test, feature = "test-support"))]
 173    pub fn build_simple(text: &str, cx: &mut gpui::MutableAppContext) -> ModelHandle<Self> {
 174        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx));
 175        cx.add_model(|cx| Self::singleton(buffer, cx))
 176    }
 177
 178    #[cfg(any(test, feature = "test-support"))]
 179    pub fn build_random(
 180        mut rng: &mut impl rand::Rng,
 181        cx: &mut gpui::MutableAppContext,
 182    ) -> ModelHandle<Self> {
 183        use rand::prelude::*;
 184        use std::env;
 185        use text::RandomCharIter;
 186
 187        let max_excerpts = env::var("MAX_EXCERPTS")
 188            .map(|i| i.parse().expect("invalid `MAX_EXCERPTS` variable"))
 189            .unwrap_or(5);
 190        let excerpts = rng.gen_range(1..=max_excerpts);
 191
 192        cx.add_model(|cx| {
 193            let mut multibuffer = MultiBuffer::new(0);
 194            let mut buffers = Vec::new();
 195            for _ in 0..excerpts {
 196                let buffer_handle = if rng.gen() || buffers.is_empty() {
 197                    let text = RandomCharIter::new(&mut rng).take(10).collect::<String>();
 198                    buffers.push(cx.add_model(|cx| Buffer::new(0, text, cx)));
 199                    let buffer = buffers.last().unwrap();
 200                    log::info!(
 201                        "Creating new buffer {} with text: {:?}",
 202                        buffer.id(),
 203                        buffer.read(cx).text()
 204                    );
 205                    buffers.last().unwrap()
 206                } else {
 207                    buffers.choose(rng).unwrap()
 208                };
 209
 210                let buffer = buffer_handle.read(cx);
 211                let end_ix = buffer.clip_offset(rng.gen_range(0..=buffer.len()), Bias::Right);
 212                let start_ix = buffer.clip_offset(rng.gen_range(0..=end_ix), Bias::Left);
 213                let header_height = rng.gen_range(0..=5);
 214                log::info!(
 215                    "Inserting excerpt from buffer {} with header height {} and range {:?}: {:?}",
 216                    buffer_handle.id(),
 217                    header_height,
 218                    start_ix..end_ix,
 219                    &buffer.text()[start_ix..end_ix]
 220                );
 221
 222                multibuffer.push_excerpt(
 223                    ExcerptProperties {
 224                        buffer: buffer_handle,
 225                        range: start_ix..end_ix,
 226                    },
 227                    cx,
 228                );
 229            }
 230            multibuffer
 231        })
 232    }
 233
 234    pub fn replica_id(&self) -> ReplicaId {
 235        self.replica_id
 236    }
 237
 238    pub fn snapshot(&self, cx: &AppContext) -> MultiBufferSnapshot {
 239        self.sync(cx);
 240        self.snapshot.borrow().clone()
 241    }
 242
 243    pub fn read(&self, cx: &AppContext) -> Ref<MultiBufferSnapshot> {
 244        self.sync(cx);
 245        self.snapshot.borrow()
 246    }
 247
 248    pub fn as_singleton(&self) -> Option<ModelHandle<Buffer>> {
 249        if self.singleton {
 250            return Some(
 251                self.buffers
 252                    .borrow()
 253                    .values()
 254                    .next()
 255                    .unwrap()
 256                    .buffer
 257                    .clone(),
 258            );
 259        } else {
 260            None
 261        }
 262    }
 263
 264    pub fn subscribe(&mut self) -> Subscription {
 265        self.subscriptions.subscribe()
 266    }
 267
 268    pub fn edit<I, S, T>(&mut self, ranges: I, new_text: T, cx: &mut ModelContext<Self>)
 269    where
 270        I: IntoIterator<Item = Range<S>>,
 271        S: ToOffset,
 272        T: Into<String>,
 273    {
 274        self.edit_internal(ranges, new_text, false, cx)
 275    }
 276
 277    pub fn edit_with_autoindent<I, S, T>(
 278        &mut self,
 279        ranges: I,
 280        new_text: T,
 281        cx: &mut ModelContext<Self>,
 282    ) where
 283        I: IntoIterator<Item = Range<S>>,
 284        S: ToOffset,
 285        T: Into<String>,
 286    {
 287        self.edit_internal(ranges, new_text, true, cx)
 288    }
 289
 290    pub fn edit_internal<I, S, T>(
 291        &mut self,
 292        ranges_iter: I,
 293        new_text: T,
 294        autoindent: bool,
 295        cx: &mut ModelContext<Self>,
 296    ) where
 297        I: IntoIterator<Item = Range<S>>,
 298        S: ToOffset,
 299        T: Into<String>,
 300    {
 301        if let Some(buffer) = self.as_singleton() {
 302            let snapshot = self.read(cx);
 303            let ranges = ranges_iter
 304                .into_iter()
 305                .map(|range| range.start.to_offset(&snapshot)..range.end.to_offset(&snapshot));
 306            return buffer.update(cx, |buffer, cx| {
 307                if autoindent {
 308                    buffer.edit_with_autoindent(ranges, new_text, cx)
 309                } else {
 310                    buffer.edit(ranges, new_text, cx)
 311                }
 312            });
 313        }
 314
 315        let snapshot = self.read(cx);
 316        let mut buffer_edits: HashMap<usize, Vec<(Range<usize>, bool)>> = Default::default();
 317        let mut cursor = snapshot.excerpts.cursor::<usize>();
 318        for range in ranges_iter {
 319            let start = range.start.to_offset(&snapshot);
 320            let end = range.end.to_offset(&snapshot);
 321            cursor.seek(&start, Bias::Right, &());
 322            if cursor.item().is_none() && start == *cursor.start() {
 323                cursor.prev(&());
 324            }
 325            let start_excerpt = cursor.item().expect("start offset out of bounds");
 326            let start_overshoot = start - cursor.start();
 327            let buffer_start =
 328                start_excerpt.range.start.to_offset(&start_excerpt.buffer) + start_overshoot;
 329
 330            cursor.seek(&end, Bias::Right, &());
 331            if cursor.item().is_none() && end == *cursor.start() {
 332                cursor.prev(&());
 333            }
 334            let end_excerpt = cursor.item().expect("end offset out of bounds");
 335            let end_overshoot = end - cursor.start();
 336            let buffer_end = end_excerpt.range.start.to_offset(&end_excerpt.buffer) + end_overshoot;
 337
 338            if start_excerpt.id == end_excerpt.id {
 339                buffer_edits
 340                    .entry(start_excerpt.buffer_id)
 341                    .or_insert(Vec::new())
 342                    .push((buffer_start..buffer_end, true));
 343            } else {
 344                let start_excerpt_range =
 345                    buffer_start..start_excerpt.range.end.to_offset(&start_excerpt.buffer);
 346                let end_excerpt_range =
 347                    end_excerpt.range.start.to_offset(&end_excerpt.buffer)..buffer_end;
 348                buffer_edits
 349                    .entry(start_excerpt.buffer_id)
 350                    .or_insert(Vec::new())
 351                    .push((start_excerpt_range, true));
 352                buffer_edits
 353                    .entry(end_excerpt.buffer_id)
 354                    .or_insert(Vec::new())
 355                    .push((end_excerpt_range, false));
 356
 357                cursor.seek(&start, Bias::Right, &());
 358                cursor.next(&());
 359                while let Some(excerpt) = cursor.item() {
 360                    if excerpt.id == end_excerpt.id {
 361                        break;
 362                    }
 363                    buffer_edits
 364                        .entry(excerpt.buffer_id)
 365                        .or_insert(Vec::new())
 366                        .push((excerpt.range.to_offset(&excerpt.buffer), false));
 367                    cursor.next(&());
 368                }
 369            }
 370        }
 371
 372        let new_text = new_text.into();
 373        for (buffer_id, mut edits) in buffer_edits {
 374            edits.sort_unstable_by_key(|(range, _)| range.start);
 375            self.buffers.borrow()[&buffer_id]
 376                .buffer
 377                .update(cx, |buffer, cx| {
 378                    let mut edits = edits.into_iter().peekable();
 379                    let mut insertions = Vec::new();
 380                    let mut deletions = Vec::new();
 381                    while let Some((mut range, mut is_insertion)) = edits.next() {
 382                        while let Some((next_range, next_is_insertion)) = edits.peek() {
 383                            if range.end >= next_range.start {
 384                                range.end = cmp::max(next_range.end, range.end);
 385                                is_insertion |= *next_is_insertion;
 386                                edits.next();
 387                            } else {
 388                                break;
 389                            }
 390                        }
 391
 392                        if is_insertion {
 393                            insertions.push(
 394                                buffer.anchor_before(range.start)..buffer.anchor_before(range.end),
 395                            );
 396                        } else if !range.is_empty() {
 397                            deletions.push(
 398                                buffer.anchor_before(range.start)..buffer.anchor_before(range.end),
 399                            );
 400                        }
 401                    }
 402
 403                    if autoindent {
 404                        buffer.edit_with_autoindent(deletions, "", cx);
 405                        buffer.edit_with_autoindent(insertions, new_text.clone(), cx);
 406                    } else {
 407                        buffer.edit(deletions, "", cx);
 408                        buffer.edit(insertions, new_text.clone(), cx);
 409                    }
 410                })
 411        }
 412    }
 413
 414    pub fn start_transaction(&mut self, cx: &mut ModelContext<Self>) -> Option<TransactionId> {
 415        self.start_transaction_at(Instant::now(), cx)
 416    }
 417
 418    pub(crate) fn start_transaction_at(
 419        &mut self,
 420        now: Instant,
 421        cx: &mut ModelContext<Self>,
 422    ) -> Option<TransactionId> {
 423        if let Some(buffer) = self.as_singleton() {
 424            return buffer.update(cx, |buffer, _| buffer.start_transaction_at(now));
 425        }
 426
 427        for BufferState { buffer, .. } in self.buffers.borrow().values() {
 428            buffer.update(cx, |buffer, _| buffer.start_transaction_at(now));
 429        }
 430        self.history.start_transaction(now)
 431    }
 432
 433    pub fn end_transaction(&mut self, cx: &mut ModelContext<Self>) -> Option<TransactionId> {
 434        self.end_transaction_at(Instant::now(), cx)
 435    }
 436
 437    pub(crate) fn end_transaction_at(
 438        &mut self,
 439        now: Instant,
 440        cx: &mut ModelContext<Self>,
 441    ) -> Option<TransactionId> {
 442        if let Some(buffer) = self.as_singleton() {
 443            return buffer.update(cx, |buffer, cx| buffer.end_transaction_at(now, cx));
 444        }
 445
 446        let mut buffer_transactions = HashSet::default();
 447        for BufferState { buffer, .. } in self.buffers.borrow().values() {
 448            if let Some(transaction_id) =
 449                buffer.update(cx, |buffer, cx| buffer.end_transaction_at(now, cx))
 450            {
 451                buffer_transactions.insert((buffer.id(), transaction_id));
 452            }
 453        }
 454
 455        if self.history.end_transaction(now, buffer_transactions) {
 456            let transaction_id = self.history.group().unwrap();
 457            Some(transaction_id)
 458        } else {
 459            None
 460        }
 461    }
 462
 463    pub fn set_active_selections(
 464        &mut self,
 465        selections: &[Selection<Anchor>],
 466        cx: &mut ModelContext<Self>,
 467    ) {
 468        let mut selections_by_buffer: HashMap<usize, Vec<Selection<text::Anchor>>> =
 469            Default::default();
 470        let snapshot = self.read(cx);
 471        let mut cursor = snapshot.excerpts.cursor::<Option<&ExcerptId>>();
 472        for selection in selections {
 473            cursor.seek(&Some(&selection.start.excerpt_id), Bias::Left, &());
 474            while let Some(excerpt) = cursor.item() {
 475                if excerpt.id > selection.end.excerpt_id {
 476                    break;
 477                }
 478
 479                let mut start = excerpt.range.start.clone();
 480                let mut end = excerpt.range.end.clone();
 481                if excerpt.id == selection.start.excerpt_id {
 482                    start = selection.start.text_anchor.clone();
 483                }
 484                if excerpt.id == selection.end.excerpt_id {
 485                    end = selection.end.text_anchor.clone();
 486                }
 487                selections_by_buffer
 488                    .entry(excerpt.buffer_id)
 489                    .or_default()
 490                    .push(Selection {
 491                        id: selection.id,
 492                        start,
 493                        end,
 494                        reversed: selection.reversed,
 495                        goal: selection.goal,
 496                    });
 497
 498                cursor.next(&());
 499            }
 500        }
 501
 502        for (buffer_id, mut selections) in selections_by_buffer {
 503            self.buffers.borrow()[&buffer_id]
 504                .buffer
 505                .update(cx, |buffer, cx| {
 506                    selections.sort_unstable_by(|a, b| a.start.cmp(&b.start, buffer).unwrap());
 507                    let mut selections = selections.into_iter().peekable();
 508                    let merged_selections = Arc::from_iter(iter::from_fn(|| {
 509                        let mut selection = selections.next()?;
 510                        while let Some(next_selection) = selections.peek() {
 511                            if selection
 512                                .end
 513                                .cmp(&next_selection.start, buffer)
 514                                .unwrap()
 515                                .is_ge()
 516                            {
 517                                let next_selection = selections.next().unwrap();
 518                                if next_selection
 519                                    .end
 520                                    .cmp(&selection.end, buffer)
 521                                    .unwrap()
 522                                    .is_ge()
 523                                {
 524                                    selection.end = next_selection.end;
 525                                }
 526                            } else {
 527                                break;
 528                            }
 529                        }
 530                        Some(selection)
 531                    }));
 532                    buffer.set_active_selections(merged_selections, cx);
 533                });
 534        }
 535    }
 536
 537    pub fn remove_active_selections(&mut self, cx: &mut ModelContext<Self>) {
 538        for buffer in self.buffers.borrow().values() {
 539            buffer
 540                .buffer
 541                .update(cx, |buffer, cx| buffer.remove_active_selections(cx));
 542        }
 543    }
 544
 545    pub fn undo(&mut self, cx: &mut ModelContext<Self>) -> Option<TransactionId> {
 546        if let Some(buffer) = self.as_singleton() {
 547            return buffer.update(cx, |buffer, cx| buffer.undo(cx));
 548        }
 549
 550        while let Some(transaction) = self.history.pop_undo() {
 551            let mut undone = false;
 552            for (buffer_id, buffer_transaction_id) in &transaction.buffer_transactions {
 553                if let Some(BufferState { buffer, .. }) = self.buffers.borrow().get(&buffer_id) {
 554                    undone |= buffer.update(cx, |buf, cx| {
 555                        buf.undo_transaction(*buffer_transaction_id, cx)
 556                    });
 557                }
 558            }
 559
 560            if undone {
 561                return Some(transaction.id);
 562            }
 563        }
 564
 565        None
 566    }
 567
 568    pub fn redo(&mut self, cx: &mut ModelContext<Self>) -> Option<TransactionId> {
 569        if let Some(buffer) = self.as_singleton() {
 570            return buffer.update(cx, |buffer, cx| buffer.redo(cx));
 571        }
 572
 573        while let Some(transaction) = self.history.pop_redo() {
 574            let mut redone = false;
 575            for (buffer_id, buffer_transaction_id) in &transaction.buffer_transactions {
 576                if let Some(BufferState { buffer, .. }) = self.buffers.borrow().get(&buffer_id) {
 577                    redone |= buffer.update(cx, |buf, cx| {
 578                        buf.redo_transaction(*buffer_transaction_id, cx)
 579                    });
 580                }
 581            }
 582
 583            if redone {
 584                return Some(transaction.id);
 585            }
 586        }
 587
 588        None
 589    }
 590
 591    pub fn push_excerpt<O>(
 592        &mut self,
 593        props: ExcerptProperties<O>,
 594        cx: &mut ModelContext<Self>,
 595    ) -> ExcerptId
 596    where
 597        O: text::ToOffset,
 598    {
 599        assert_eq!(self.history.transaction_depth, 0);
 600        self.sync(cx);
 601
 602        let buffer_snapshot = props.buffer.read(cx).snapshot();
 603        let range = buffer_snapshot.anchor_before(&props.range.start)
 604            ..buffer_snapshot.anchor_after(&props.range.end);
 605        let mut snapshot = self.snapshot.borrow_mut();
 606        let mut prev_id = None;
 607        let edit_start = snapshot.excerpts.summary().text.bytes;
 608        snapshot.excerpts.update_last(
 609            |excerpt| {
 610                excerpt.has_trailing_newline = true;
 611                prev_id = Some(excerpt.id.clone());
 612            },
 613            &(),
 614        );
 615
 616        let id = ExcerptId::between(&prev_id.unwrap_or(ExcerptId::min()), &ExcerptId::max());
 617        self.buffers
 618            .borrow_mut()
 619            .entry(props.buffer.id())
 620            .or_insert_with(|| BufferState {
 621                last_version: buffer_snapshot.version().clone(),
 622                last_parse_count: buffer_snapshot.parse_count(),
 623                last_diagnostics_update_count: buffer_snapshot.diagnostics_update_count(),
 624                excerpts: Default::default(),
 625                _subscriptions: [
 626                    cx.observe(&props.buffer, |_, _, cx| cx.notify()),
 627                    cx.subscribe(&props.buffer, Self::on_buffer_event),
 628                ],
 629                buffer: props.buffer.clone(),
 630            })
 631            .excerpts
 632            .push(id.clone());
 633        let excerpt = Excerpt::new(id.clone(), props.buffer.id(), buffer_snapshot, range, false);
 634        snapshot.excerpts.push(excerpt, &());
 635        self.subscriptions.publish_mut([Edit {
 636            old: edit_start..edit_start,
 637            new: edit_start..snapshot.excerpts.summary().text.bytes,
 638        }]);
 639
 640        cx.notify();
 641        id
 642    }
 643
 644    pub fn excerpt_ids_for_buffer(&self, buffer: &ModelHandle<Buffer>) -> Vec<ExcerptId> {
 645        self.buffers
 646            .borrow()
 647            .get(&buffer.id())
 648            .map_or(Vec::new(), |state| state.excerpts.clone())
 649    }
 650
 651    pub fn remove_excerpts<'a>(
 652        &mut self,
 653        excerpt_ids: impl IntoIterator<Item = &'a ExcerptId>,
 654        cx: &mut ModelContext<Self>,
 655    ) {
 656        let mut buffers = self.buffers.borrow_mut();
 657        let mut snapshot = self.snapshot.borrow_mut();
 658        let mut new_excerpts = SumTree::new();
 659        let mut cursor = snapshot.excerpts.cursor::<(Option<&ExcerptId>, usize)>();
 660        let mut edits = Vec::new();
 661        for excerpt_id in excerpt_ids {
 662            new_excerpts.push_tree(cursor.slice(&Some(excerpt_id), Bias::Left, &()), &());
 663            if let Some(excerpt) = cursor.item() {
 664                if excerpt.id == *excerpt_id {
 665                    let mut old_start = cursor.start().1;
 666                    let old_end = cursor.end(&()).1;
 667                    cursor.next(&());
 668
 669                    if let Some(buffer_state) = buffers.get_mut(&excerpt.buffer_id) {
 670                        buffer_state.excerpts.retain(|id| id != excerpt_id);
 671                    }
 672
 673                    // When removing the last excerpt, remove the trailing newline from
 674                    // the previous excerpt.
 675                    if cursor.item().is_none() && old_start > 0 {
 676                        old_start -= 1;
 677                        new_excerpts.update_last(|e| e.has_trailing_newline = false, &());
 678                    }
 679
 680                    let new_start = new_excerpts.summary().text.bytes;
 681                    edits.push(Edit {
 682                        old: old_start..old_end,
 683                        new: new_start..new_start,
 684                    });
 685                }
 686            }
 687        }
 688        new_excerpts.push_tree(cursor.suffix(&()), &());
 689        drop(cursor);
 690        snapshot.excerpts = new_excerpts;
 691        self.subscriptions.publish_mut(edits);
 692        cx.notify();
 693    }
 694
 695    fn on_buffer_event(
 696        &mut self,
 697        _: ModelHandle<Buffer>,
 698        event: &Event,
 699        cx: &mut ModelContext<Self>,
 700    ) {
 701        cx.emit(event.clone());
 702    }
 703
 704    pub fn save(&mut self, cx: &mut ModelContext<Self>) -> Result<Task<Result<()>>> {
 705        let mut save_tasks = Vec::new();
 706        for BufferState { buffer, .. } in self.buffers.borrow().values() {
 707            save_tasks.push(buffer.update(cx, |buffer, cx| buffer.save(cx))?);
 708        }
 709
 710        Ok(cx.spawn(|_, _| async move {
 711            for save in save_tasks {
 712                save.await?;
 713            }
 714            Ok(())
 715        }))
 716    }
 717
 718    pub fn language<'a>(&self, cx: &'a AppContext) -> Option<&'a Arc<Language>> {
 719        self.buffers
 720            .borrow()
 721            .values()
 722            .next()
 723            .and_then(|state| state.buffer.read(cx).language())
 724    }
 725
 726    pub fn file<'a>(&self, cx: &'a AppContext) -> Option<&'a dyn File> {
 727        self.as_singleton()?.read(cx).file()
 728    }
 729
 730    #[cfg(test)]
 731    pub fn is_parsing(&self, cx: &AppContext) -> bool {
 732        self.as_singleton().unwrap().read(cx).is_parsing()
 733    }
 734
 735    fn sync(&self, cx: &AppContext) {
 736        let mut snapshot = self.snapshot.borrow_mut();
 737        let mut excerpts_to_edit = Vec::new();
 738        let mut reparsed = false;
 739        let mut diagnostics_updated = false;
 740        let mut is_dirty = false;
 741        let mut has_conflict = false;
 742        let mut buffers = self.buffers.borrow_mut();
 743        for buffer_state in buffers.values_mut() {
 744            let buffer = buffer_state.buffer.read(cx);
 745            let version = buffer.version();
 746            let parse_count = buffer.parse_count();
 747            let diagnostics_update_count = buffer.diagnostics_update_count();
 748
 749            let buffer_edited = version.gt(&buffer_state.last_version);
 750            let buffer_reparsed = parse_count > buffer_state.last_parse_count;
 751            let buffer_diagnostics_updated =
 752                diagnostics_update_count > buffer_state.last_diagnostics_update_count;
 753            if buffer_edited || buffer_reparsed || buffer_diagnostics_updated {
 754                buffer_state.last_version = version;
 755                buffer_state.last_parse_count = parse_count;
 756                buffer_state.last_diagnostics_update_count = diagnostics_update_count;
 757                excerpts_to_edit.extend(
 758                    buffer_state
 759                        .excerpts
 760                        .iter()
 761                        .map(|excerpt_id| (excerpt_id, buffer_state.buffer.clone(), buffer_edited)),
 762                );
 763            }
 764
 765            reparsed |= buffer_reparsed;
 766            diagnostics_updated |= buffer_diagnostics_updated;
 767            is_dirty |= buffer.is_dirty();
 768            has_conflict |= buffer.has_conflict();
 769        }
 770        if reparsed {
 771            snapshot.parse_count += 1;
 772        }
 773        if diagnostics_updated {
 774            snapshot.diagnostics_update_count += 1;
 775        }
 776        snapshot.is_dirty = is_dirty;
 777        snapshot.has_conflict = has_conflict;
 778
 779        excerpts_to_edit.sort_unstable_by_key(|(excerpt_id, _, _)| *excerpt_id);
 780
 781        let mut edits = Vec::new();
 782        let mut new_excerpts = SumTree::new();
 783        let mut cursor = snapshot.excerpts.cursor::<(Option<&ExcerptId>, usize)>();
 784
 785        for (id, buffer, buffer_edited) in excerpts_to_edit {
 786            new_excerpts.push_tree(cursor.slice(&Some(id), Bias::Left, &()), &());
 787            let old_excerpt = cursor.item().unwrap();
 788            let buffer_id = buffer.id();
 789            let buffer = buffer.read(cx);
 790
 791            let mut new_excerpt;
 792            if buffer_edited {
 793                edits.extend(
 794                    buffer
 795                        .edits_since_in_range::<usize>(
 796                            old_excerpt.buffer.version(),
 797                            old_excerpt.range.clone(),
 798                        )
 799                        .map(|mut edit| {
 800                            let excerpt_old_start = cursor.start().1;
 801                            let excerpt_new_start = new_excerpts.summary().text.bytes;
 802                            edit.old.start += excerpt_old_start;
 803                            edit.old.end += excerpt_old_start;
 804                            edit.new.start += excerpt_new_start;
 805                            edit.new.end += excerpt_new_start;
 806                            edit
 807                        }),
 808                );
 809
 810                new_excerpt = Excerpt::new(
 811                    id.clone(),
 812                    buffer_id,
 813                    buffer.snapshot(),
 814                    old_excerpt.range.clone(),
 815                    old_excerpt.has_trailing_newline,
 816                );
 817            } else {
 818                new_excerpt = old_excerpt.clone();
 819                new_excerpt.buffer = buffer.snapshot();
 820            }
 821
 822            new_excerpts.push(new_excerpt, &());
 823            cursor.next(&());
 824        }
 825        new_excerpts.push_tree(cursor.suffix(&()), &());
 826
 827        drop(cursor);
 828        snapshot.excerpts = new_excerpts;
 829
 830        self.subscriptions.publish(edits);
 831    }
 832}
 833
 834#[cfg(any(test, feature = "test-support"))]
 835impl MultiBuffer {
 836    pub fn randomly_edit(
 837        &mut self,
 838        rng: &mut impl rand::Rng,
 839        count: usize,
 840        cx: &mut ModelContext<Self>,
 841    ) {
 842        use text::RandomCharIter;
 843
 844        let snapshot = self.read(cx);
 845        let mut old_ranges: Vec<Range<usize>> = Vec::new();
 846        for _ in 0..count {
 847            let last_end = old_ranges.last().map_or(0, |last_range| last_range.end + 1);
 848            if last_end > snapshot.len() {
 849                break;
 850            }
 851            let end_ix = snapshot.clip_offset(rng.gen_range(0..=last_end), Bias::Right);
 852            let start_ix = snapshot.clip_offset(rng.gen_range(0..=end_ix), Bias::Left);
 853            old_ranges.push(start_ix..end_ix);
 854        }
 855        let new_text_len = rng.gen_range(0..10);
 856        let new_text: String = RandomCharIter::new(&mut *rng).take(new_text_len).collect();
 857        log::info!("mutating multi-buffer at {:?}: {:?}", old_ranges, new_text);
 858        drop(snapshot);
 859
 860        self.edit(old_ranges.iter().cloned(), new_text.as_str(), cx);
 861    }
 862}
 863
 864impl Entity for MultiBuffer {
 865    type Event = language::Event;
 866}
 867
 868impl MultiBufferSnapshot {
 869    pub fn text(&self) -> String {
 870        self.chunks(0..self.len(), None)
 871            .map(|chunk| chunk.text)
 872            .collect()
 873    }
 874
 875    pub fn reversed_chars_at<'a, T: ToOffset>(
 876        &'a self,
 877        position: T,
 878    ) -> impl Iterator<Item = char> + 'a {
 879        let mut offset = position.to_offset(self);
 880        let mut cursor = self.excerpts.cursor::<usize>();
 881        cursor.seek(&offset, Bias::Left, &());
 882        let mut excerpt_chunks = cursor.item().map(|excerpt| {
 883            let end_before_footer = cursor.start() + excerpt.text_summary.bytes;
 884            let start = excerpt.range.start.to_offset(&excerpt.buffer);
 885            let end = start + (cmp::min(offset, end_before_footer) - cursor.start());
 886            excerpt.buffer.reversed_chunks_in_range(start..end)
 887        });
 888        iter::from_fn(move || {
 889            if offset == *cursor.start() {
 890                cursor.prev(&());
 891                let excerpt = cursor.item()?;
 892                excerpt_chunks = Some(
 893                    excerpt
 894                        .buffer
 895                        .reversed_chunks_in_range(excerpt.range.clone()),
 896                );
 897            }
 898
 899            let excerpt = cursor.item().unwrap();
 900            if offset == cursor.end(&()) && excerpt.has_trailing_newline {
 901                offset -= 1;
 902                Some("\n")
 903            } else {
 904                let chunk = excerpt_chunks.as_mut().unwrap().next().unwrap();
 905                offset -= chunk.len();
 906                Some(chunk)
 907            }
 908        })
 909        .flat_map(|c| c.chars().rev())
 910    }
 911
 912    pub fn chars_at<'a, T: ToOffset>(&'a self, position: T) -> impl Iterator<Item = char> + 'a {
 913        let offset = position.to_offset(self);
 914        self.text_for_range(offset..self.len())
 915            .flat_map(|chunk| chunk.chars())
 916    }
 917
 918    pub fn text_for_range<'a, T: ToOffset>(
 919        &'a self,
 920        range: Range<T>,
 921    ) -> impl Iterator<Item = &'a str> {
 922        self.chunks(range, None).map(|chunk| chunk.text)
 923    }
 924
 925    pub fn is_line_blank(&self, row: u32) -> bool {
 926        self.text_for_range(Point::new(row, 0)..Point::new(row, self.line_len(row)))
 927            .all(|chunk| chunk.matches(|c: char| !c.is_whitespace()).next().is_none())
 928    }
 929
 930    pub fn contains_str_at<T>(&self, position: T, needle: &str) -> bool
 931    where
 932        T: ToOffset,
 933    {
 934        let position = position.to_offset(self);
 935        position == self.clip_offset(position, Bias::Left)
 936            && self
 937                .bytes_in_range(position..self.len())
 938                .flatten()
 939                .copied()
 940                .take(needle.len())
 941                .eq(needle.bytes())
 942    }
 943
 944    fn as_singleton(&self) -> Option<&BufferSnapshot> {
 945        let mut excerpts = self.excerpts.iter();
 946        let buffer = excerpts.next().map(|excerpt| &excerpt.buffer);
 947        if excerpts.next().is_none() {
 948            buffer
 949        } else {
 950            None
 951        }
 952    }
 953
 954    pub fn len(&self) -> usize {
 955        self.excerpts.summary().text.bytes
 956    }
 957
 958    pub fn max_buffer_row(&self) -> u32 {
 959        self.excerpts.summary().max_buffer_row
 960    }
 961
 962    pub fn clip_offset(&self, offset: usize, bias: Bias) -> usize {
 963        let mut cursor = self.excerpts.cursor::<usize>();
 964        cursor.seek(&offset, Bias::Right, &());
 965        let overshoot = if let Some(excerpt) = cursor.item() {
 966            let excerpt_start = excerpt.range.start.to_offset(&excerpt.buffer);
 967            let buffer_offset = excerpt
 968                .buffer
 969                .clip_offset(excerpt_start + (offset - cursor.start()), bias);
 970            buffer_offset.saturating_sub(excerpt_start)
 971        } else {
 972            0
 973        };
 974        cursor.start() + overshoot
 975    }
 976
 977    pub fn clip_point(&self, point: Point, bias: Bias) -> Point {
 978        let mut cursor = self.excerpts.cursor::<Point>();
 979        cursor.seek(&point, Bias::Right, &());
 980        let overshoot = if let Some(excerpt) = cursor.item() {
 981            let excerpt_start = excerpt.range.start.to_point(&excerpt.buffer);
 982            let buffer_point = excerpt
 983                .buffer
 984                .clip_point(excerpt_start + (point - cursor.start()), bias);
 985            buffer_point.saturating_sub(excerpt_start)
 986        } else {
 987            Point::zero()
 988        };
 989        *cursor.start() + overshoot
 990    }
 991
 992    pub fn clip_point_utf16(&self, point: PointUtf16, bias: Bias) -> PointUtf16 {
 993        let mut cursor = self.excerpts.cursor::<PointUtf16>();
 994        cursor.seek(&point, Bias::Right, &());
 995        let overshoot = if let Some(excerpt) = cursor.item() {
 996            let excerpt_start = excerpt
 997                .buffer
 998                .offset_to_point_utf16(excerpt.range.start.to_offset(&excerpt.buffer));
 999            let buffer_point = excerpt
1000                .buffer
1001                .clip_point_utf16(excerpt_start + (point - cursor.start()), bias);
1002            buffer_point.saturating_sub(excerpt_start)
1003        } else {
1004            PointUtf16::zero()
1005        };
1006        *cursor.start() + overshoot
1007    }
1008
1009    pub fn bytes_in_range<'a, T: ToOffset>(&'a self, range: Range<T>) -> MultiBufferBytes<'a> {
1010        let range = range.start.to_offset(self)..range.end.to_offset(self);
1011        let mut excerpts = self.excerpts.cursor::<usize>();
1012        excerpts.seek(&range.start, Bias::Right, &());
1013
1014        let mut chunk = &[][..];
1015        let excerpt_bytes = if let Some(excerpt) = excerpts.item() {
1016            let mut excerpt_bytes = excerpt
1017                .bytes_in_range(range.start - excerpts.start()..range.end - excerpts.start());
1018            chunk = excerpt_bytes.next().unwrap_or(&[][..]);
1019            Some(excerpt_bytes)
1020        } else {
1021            None
1022        };
1023
1024        MultiBufferBytes {
1025            range,
1026            excerpts,
1027            excerpt_bytes,
1028            chunk,
1029        }
1030    }
1031
1032    pub fn buffer_rows<'a>(&'a self, start_row: u32) -> MultiBufferRows<'a> {
1033        let mut result = MultiBufferRows {
1034            buffer_row_range: 0..0,
1035            excerpts: self.excerpts.cursor(),
1036        };
1037        result.seek(start_row);
1038        result
1039    }
1040
1041    pub fn chunks<'a, T: ToOffset>(
1042        &'a self,
1043        range: Range<T>,
1044        theme: Option<&'a SyntaxTheme>,
1045    ) -> MultiBufferChunks<'a> {
1046        let range = range.start.to_offset(self)..range.end.to_offset(self);
1047        let mut chunks = MultiBufferChunks {
1048            range: range.clone(),
1049            excerpts: self.excerpts.cursor(),
1050            excerpt_chunks: None,
1051            theme,
1052        };
1053        chunks.seek(range.start);
1054        chunks
1055    }
1056
1057    pub fn offset_to_point(&self, offset: usize) -> Point {
1058        let mut cursor = self.excerpts.cursor::<(usize, Point)>();
1059        cursor.seek(&offset, Bias::Right, &());
1060        if let Some(excerpt) = cursor.item() {
1061            let (start_offset, start_point) = cursor.start();
1062            let overshoot = offset - start_offset;
1063            let excerpt_start_offset = excerpt.range.start.to_offset(&excerpt.buffer);
1064            let excerpt_start_point = excerpt.range.start.to_point(&excerpt.buffer);
1065            let buffer_point = excerpt
1066                .buffer
1067                .offset_to_point(excerpt_start_offset + overshoot);
1068            *start_point + (buffer_point - excerpt_start_point)
1069        } else {
1070            self.excerpts.summary().text.lines
1071        }
1072    }
1073
1074    pub fn point_to_offset(&self, point: Point) -> usize {
1075        let mut cursor = self.excerpts.cursor::<(Point, usize)>();
1076        cursor.seek(&point, Bias::Right, &());
1077        if let Some(excerpt) = cursor.item() {
1078            let (start_point, start_offset) = cursor.start();
1079            let overshoot = point - start_point;
1080            let excerpt_start_offset = excerpt.range.start.to_offset(&excerpt.buffer);
1081            let excerpt_start_point = excerpt.range.start.to_point(&excerpt.buffer);
1082            let buffer_offset = excerpt
1083                .buffer
1084                .point_to_offset(excerpt_start_point + overshoot);
1085            *start_offset + buffer_offset - excerpt_start_offset
1086        } else {
1087            self.excerpts.summary().text.bytes
1088        }
1089    }
1090
1091    pub fn point_utf16_to_offset(&self, point: PointUtf16) -> usize {
1092        let mut cursor = self.excerpts.cursor::<(PointUtf16, usize)>();
1093        cursor.seek(&point, Bias::Right, &());
1094        if let Some(excerpt) = cursor.item() {
1095            let (start_point, start_offset) = cursor.start();
1096            let overshoot = point - start_point;
1097            let excerpt_start_offset = excerpt.range.start.to_offset(&excerpt.buffer);
1098            let excerpt_start_point = excerpt
1099                .buffer
1100                .offset_to_point_utf16(excerpt.range.start.to_offset(&excerpt.buffer));
1101            let buffer_offset = excerpt
1102                .buffer
1103                .point_utf16_to_offset(excerpt_start_point + overshoot);
1104            *start_offset + (buffer_offset - excerpt_start_offset)
1105        } else {
1106            self.excerpts.summary().text.bytes
1107        }
1108    }
1109
1110    pub fn indent_column_for_line(&self, row: u32) -> u32 {
1111        if let Some((buffer, range)) = self.buffer_line_for_row(row) {
1112            buffer
1113                .indent_column_for_line(range.start.row)
1114                .min(range.end.column)
1115                .saturating_sub(range.start.column)
1116        } else {
1117            0
1118        }
1119    }
1120
1121    pub fn line_len(&self, row: u32) -> u32 {
1122        if let Some((_, range)) = self.buffer_line_for_row(row) {
1123            range.end.column - range.start.column
1124        } else {
1125            0
1126        }
1127    }
1128
1129    fn buffer_line_for_row(&self, row: u32) -> Option<(&BufferSnapshot, Range<Point>)> {
1130        let mut cursor = self.excerpts.cursor::<Point>();
1131        cursor.seek(&Point::new(row, 0), Bias::Right, &());
1132        if let Some(excerpt) = cursor.item() {
1133            let overshoot = row - cursor.start().row;
1134            let excerpt_start = excerpt.range.start.to_point(&excerpt.buffer);
1135            let excerpt_end = excerpt.range.end.to_point(&excerpt.buffer);
1136            let buffer_row = excerpt_start.row + overshoot;
1137            let line_start = Point::new(buffer_row, 0);
1138            let line_end = Point::new(buffer_row, excerpt.buffer.line_len(buffer_row));
1139            return Some((
1140                &excerpt.buffer,
1141                line_start.max(excerpt_start)..line_end.min(excerpt_end),
1142            ));
1143        }
1144        None
1145    }
1146
1147    pub fn max_point(&self) -> Point {
1148        self.text_summary().lines
1149    }
1150
1151    pub fn text_summary(&self) -> TextSummary {
1152        self.excerpts.summary().text
1153    }
1154
1155    pub fn text_summary_for_range<'a, D, O>(&'a self, range: Range<O>) -> D
1156    where
1157        D: TextDimension,
1158        O: ToOffset,
1159    {
1160        let mut summary = D::default();
1161        let mut range = range.start.to_offset(self)..range.end.to_offset(self);
1162        let mut cursor = self.excerpts.cursor::<usize>();
1163        cursor.seek(&range.start, Bias::Right, &());
1164        if let Some(excerpt) = cursor.item() {
1165            let mut end_before_newline = cursor.end(&());
1166            if excerpt.has_trailing_newline {
1167                end_before_newline -= 1;
1168            }
1169
1170            let excerpt_start = excerpt.range.start.to_offset(&excerpt.buffer);
1171            let start_in_excerpt = excerpt_start + (range.start - cursor.start());
1172            let end_in_excerpt =
1173                excerpt_start + (cmp::min(end_before_newline, range.end) - cursor.start());
1174            summary.add_assign(
1175                &excerpt
1176                    .buffer
1177                    .text_summary_for_range(start_in_excerpt..end_in_excerpt),
1178            );
1179
1180            if range.end > end_before_newline {
1181                summary.add_assign(&D::from_text_summary(&TextSummary {
1182                    bytes: 1,
1183                    lines: Point::new(1 as u32, 0),
1184                    lines_utf16: PointUtf16::new(1 as u32, 0),
1185                    first_line_chars: 0,
1186                    last_line_chars: 0,
1187                    longest_row: 0,
1188                    longest_row_chars: 0,
1189                }));
1190            }
1191
1192            cursor.next(&());
1193        }
1194
1195        if range.end > *cursor.start() {
1196            summary.add_assign(&D::from_text_summary(&cursor.summary::<_, TextSummary>(
1197                &range.end,
1198                Bias::Right,
1199                &(),
1200            )));
1201            if let Some(excerpt) = cursor.item() {
1202                range.end = cmp::max(*cursor.start(), range.end);
1203
1204                let excerpt_start = excerpt.range.start.to_offset(&excerpt.buffer);
1205                let end_in_excerpt = excerpt_start + (range.end - cursor.start());
1206                summary.add_assign(
1207                    &excerpt
1208                        .buffer
1209                        .text_summary_for_range(excerpt_start..end_in_excerpt),
1210                );
1211            }
1212        }
1213
1214        summary
1215    }
1216
1217    pub fn summary_for_anchor<D>(&self, anchor: &Anchor) -> D
1218    where
1219        D: TextDimension + Ord + Sub<D, Output = D>,
1220    {
1221        let mut cursor = self.excerpts.cursor::<ExcerptSummary>();
1222        cursor.seek(&Some(&anchor.excerpt_id), Bias::Left, &());
1223        if cursor.item().is_none() {
1224            cursor.next(&());
1225        }
1226
1227        let mut position = D::from_text_summary(&cursor.start().text);
1228        if let Some(excerpt) = cursor.item() {
1229            if excerpt.id == anchor.excerpt_id {
1230                let excerpt_buffer_start = excerpt.range.start.summary::<D>(&excerpt.buffer);
1231                let buffer_position = anchor.text_anchor.summary::<D>(&excerpt.buffer);
1232                if buffer_position > excerpt_buffer_start {
1233                    position.add_assign(&(buffer_position - excerpt_buffer_start));
1234                }
1235            }
1236        }
1237        position
1238    }
1239
1240    pub fn summaries_for_anchors<'a, D, I>(&'a self, anchors: I) -> Vec<D>
1241    where
1242        D: TextDimension + Ord + Sub<D, Output = D>,
1243        I: 'a + IntoIterator<Item = &'a Anchor>,
1244    {
1245        let mut anchors = anchors.into_iter().peekable();
1246        let mut cursor = self.excerpts.cursor::<ExcerptSummary>();
1247        let mut summaries = Vec::new();
1248        while let Some(anchor) = anchors.peek() {
1249            let excerpt_id = &anchor.excerpt_id;
1250            let excerpt_anchors = iter::from_fn(|| {
1251                let anchor = anchors.peek()?;
1252                if anchor.excerpt_id == *excerpt_id {
1253                    Some(&anchors.next().unwrap().text_anchor)
1254                } else {
1255                    None
1256                }
1257            });
1258
1259            cursor.seek_forward(&Some(excerpt_id), Bias::Left, &());
1260            if cursor.item().is_none() {
1261                cursor.next(&());
1262            }
1263
1264            let position = D::from_text_summary(&cursor.start().text);
1265            if let Some(excerpt) = cursor.item() {
1266                if excerpt.id == *excerpt_id {
1267                    let excerpt_buffer_start = excerpt.range.start.summary::<D>(&excerpt.buffer);
1268                    summaries.extend(
1269                        excerpt
1270                            .buffer
1271                            .summaries_for_anchors::<D, _>(excerpt_anchors)
1272                            .map(move |summary| {
1273                                let mut position = position.clone();
1274                                let excerpt_buffer_start = excerpt_buffer_start.clone();
1275                                if summary > excerpt_buffer_start {
1276                                    position.add_assign(&(summary - excerpt_buffer_start));
1277                                }
1278                                position
1279                            }),
1280                    );
1281                    continue;
1282                }
1283            }
1284
1285            summaries.extend(excerpt_anchors.map(|_| position.clone()));
1286        }
1287
1288        summaries
1289    }
1290
1291    pub fn anchor_before<T: ToOffset>(&self, position: T) -> Anchor {
1292        self.anchor_at(position, Bias::Left)
1293    }
1294
1295    pub fn anchor_after<T: ToOffset>(&self, position: T) -> Anchor {
1296        self.anchor_at(position, Bias::Right)
1297    }
1298
1299    pub fn anchor_at<T: ToOffset>(&self, position: T, mut bias: Bias) -> Anchor {
1300        let offset = position.to_offset(self);
1301        let mut cursor = self.excerpts.cursor::<(usize, Option<&ExcerptId>)>();
1302        cursor.seek(&offset, Bias::Right, &());
1303        if cursor.item().is_none() && offset == cursor.start().0 && bias == Bias::Left {
1304            cursor.prev(&());
1305        }
1306        if let Some(excerpt) = cursor.item() {
1307            let mut overshoot = offset.saturating_sub(cursor.start().0);
1308            if excerpt.has_trailing_newline && offset == cursor.end(&()).0 {
1309                overshoot -= 1;
1310                bias = Bias::Right;
1311            }
1312
1313            let buffer_start = excerpt.range.start.to_offset(&excerpt.buffer);
1314            let text_anchor =
1315                excerpt.clip_anchor(excerpt.buffer.anchor_at(buffer_start + overshoot, bias));
1316            Anchor {
1317                excerpt_id: excerpt.id.clone(),
1318                text_anchor,
1319            }
1320        } else if offset == 0 && bias == Bias::Left {
1321            Anchor::min()
1322        } else {
1323            Anchor::max()
1324        }
1325    }
1326
1327    pub fn anchor_in_excerpt(&self, excerpt_id: ExcerptId, text_anchor: text::Anchor) -> Anchor {
1328        let mut cursor = self.excerpts.cursor::<Option<&ExcerptId>>();
1329        cursor.seek(&Some(&excerpt_id), Bias::Left, &());
1330        if let Some(excerpt) = cursor.item() {
1331            if excerpt.id == excerpt_id {
1332                let text_anchor = excerpt.clip_anchor(text_anchor);
1333                drop(cursor);
1334                return Anchor {
1335                    excerpt_id,
1336                    text_anchor,
1337                };
1338            }
1339        }
1340        panic!("excerpt not found");
1341    }
1342
1343    pub fn parse_count(&self) -> usize {
1344        self.parse_count
1345    }
1346
1347    pub fn enclosing_bracket_ranges<T: ToOffset>(
1348        &self,
1349        range: Range<T>,
1350    ) -> Option<(Range<usize>, Range<usize>)> {
1351        let range = range.start.to_offset(self)..range.end.to_offset(self);
1352
1353        let mut cursor = self.excerpts.cursor::<usize>();
1354        cursor.seek(&range.start, Bias::Right, &());
1355        let start_excerpt = cursor.item();
1356
1357        cursor.seek(&range.end, Bias::Right, &());
1358        let end_excerpt = cursor.item();
1359
1360        start_excerpt
1361            .zip(end_excerpt)
1362            .and_then(|(start_excerpt, end_excerpt)| {
1363                if start_excerpt.id != end_excerpt.id {
1364                    return None;
1365                }
1366
1367                let excerpt_buffer_start =
1368                    start_excerpt.range.start.to_offset(&start_excerpt.buffer);
1369                let excerpt_buffer_end = excerpt_buffer_start + start_excerpt.text_summary.bytes;
1370
1371                let start_in_buffer =
1372                    excerpt_buffer_start + range.start.saturating_sub(*cursor.start());
1373                let end_in_buffer =
1374                    excerpt_buffer_start + range.end.saturating_sub(*cursor.start());
1375                let (mut start_bracket_range, mut end_bracket_range) = start_excerpt
1376                    .buffer
1377                    .enclosing_bracket_ranges(start_in_buffer..end_in_buffer)?;
1378
1379                if start_bracket_range.start >= excerpt_buffer_start
1380                    && end_bracket_range.end < excerpt_buffer_end
1381                {
1382                    start_bracket_range.start =
1383                        cursor.start() + (start_bracket_range.start - excerpt_buffer_start);
1384                    start_bracket_range.end =
1385                        cursor.start() + (start_bracket_range.end - excerpt_buffer_start);
1386                    end_bracket_range.start =
1387                        cursor.start() + (end_bracket_range.start - excerpt_buffer_start);
1388                    end_bracket_range.end =
1389                        cursor.start() + (end_bracket_range.end - excerpt_buffer_start);
1390                    Some((start_bracket_range, end_bracket_range))
1391                } else {
1392                    None
1393                }
1394            })
1395    }
1396
1397    pub fn diagnostics_update_count(&self) -> usize {
1398        self.diagnostics_update_count
1399    }
1400
1401    pub fn language(&self) -> Option<&Arc<Language>> {
1402        self.excerpts
1403            .iter()
1404            .next()
1405            .and_then(|excerpt| excerpt.buffer.language())
1406    }
1407
1408    pub fn is_dirty(&self) -> bool {
1409        self.is_dirty
1410    }
1411
1412    pub fn has_conflict(&self) -> bool {
1413        self.has_conflict
1414    }
1415
1416    pub fn diagnostic_group<'a, O>(
1417        &'a self,
1418        group_id: usize,
1419    ) -> impl Iterator<Item = DiagnosticEntry<O>> + 'a
1420    where
1421        O: text::FromAnchor + 'a,
1422    {
1423        self.as_singleton()
1424            .into_iter()
1425            .flat_map(move |buffer| buffer.diagnostic_group(group_id))
1426    }
1427
1428    pub fn diagnostics_in_range<'a, T, O>(
1429        &'a self,
1430        range: Range<T>,
1431    ) -> impl Iterator<Item = DiagnosticEntry<O>> + 'a
1432    where
1433        T: 'a + ToOffset,
1434        O: 'a + text::FromAnchor,
1435    {
1436        self.as_singleton().into_iter().flat_map(move |buffer| {
1437            buffer.diagnostics_in_range(range.start.to_offset(self)..range.end.to_offset(self))
1438        })
1439    }
1440
1441    pub fn range_for_syntax_ancestor<T: ToOffset>(&self, range: Range<T>) -> Option<Range<usize>> {
1442        let range = range.start.to_offset(self)..range.end.to_offset(self);
1443
1444        let mut cursor = self.excerpts.cursor::<usize>();
1445        cursor.seek(&range.start, Bias::Right, &());
1446        let start_excerpt = cursor.item();
1447
1448        cursor.seek(&range.end, Bias::Right, &());
1449        let end_excerpt = cursor.item();
1450
1451        start_excerpt
1452            .zip(end_excerpt)
1453            .and_then(|(start_excerpt, end_excerpt)| {
1454                if start_excerpt.id != end_excerpt.id {
1455                    return None;
1456                }
1457
1458                let excerpt_buffer_start =
1459                    start_excerpt.range.start.to_offset(&start_excerpt.buffer);
1460                let excerpt_buffer_end = excerpt_buffer_start + start_excerpt.text_summary.bytes;
1461
1462                let start_in_buffer =
1463                    excerpt_buffer_start + range.start.saturating_sub(*cursor.start());
1464                let end_in_buffer =
1465                    excerpt_buffer_start + range.end.saturating_sub(*cursor.start());
1466                let mut ancestor_buffer_range = start_excerpt
1467                    .buffer
1468                    .range_for_syntax_ancestor(start_in_buffer..end_in_buffer)?;
1469                ancestor_buffer_range.start =
1470                    cmp::max(ancestor_buffer_range.start, excerpt_buffer_start);
1471                ancestor_buffer_range.end = cmp::min(ancestor_buffer_range.end, excerpt_buffer_end);
1472
1473                let start = cursor.start() + (ancestor_buffer_range.start - excerpt_buffer_start);
1474                let end = cursor.start() + (ancestor_buffer_range.end - excerpt_buffer_start);
1475                Some(start..end)
1476            })
1477    }
1478
1479    fn buffer_snapshot_for_excerpt<'a>(
1480        &'a self,
1481        excerpt_id: &'a ExcerptId,
1482    ) -> Option<&'a BufferSnapshot> {
1483        let mut cursor = self.excerpts.cursor::<Option<&ExcerptId>>();
1484        cursor.seek(&Some(excerpt_id), Bias::Left, &());
1485        if let Some(excerpt) = cursor.item() {
1486            if excerpt.id == *excerpt_id {
1487                return Some(&excerpt.buffer);
1488            }
1489        }
1490        None
1491    }
1492
1493    pub fn remote_selections_in_range<'a>(
1494        &'a self,
1495        range: &'a Range<Anchor>,
1496    ) -> impl 'a + Iterator<Item = (ReplicaId, Selection<Anchor>)> {
1497        let mut cursor = self.excerpts.cursor::<Option<&ExcerptId>>();
1498        cursor.seek(&Some(&range.start.excerpt_id), Bias::Left, &());
1499        cursor
1500            .take_while(move |excerpt| excerpt.id <= range.end.excerpt_id)
1501            .flat_map(move |excerpt| {
1502                let mut query_range = excerpt.range.start.clone()..excerpt.range.end.clone();
1503                if excerpt.id == range.start.excerpt_id {
1504                    query_range.start = range.start.text_anchor.clone();
1505                }
1506                if excerpt.id == range.end.excerpt_id {
1507                    query_range.end = range.end.text_anchor.clone();
1508                }
1509
1510                excerpt
1511                    .buffer
1512                    .remote_selections_in_range(query_range)
1513                    .flat_map(move |(replica_id, selections)| {
1514                        selections.map(move |selection| {
1515                            let mut start = Anchor {
1516                                excerpt_id: excerpt.id.clone(),
1517                                text_anchor: selection.start.clone(),
1518                            };
1519                            let mut end = Anchor {
1520                                excerpt_id: excerpt.id.clone(),
1521                                text_anchor: selection.end.clone(),
1522                            };
1523                            if range.start.cmp(&start, self).unwrap().is_gt() {
1524                                start = range.start.clone();
1525                            }
1526                            if range.end.cmp(&end, self).unwrap().is_lt() {
1527                                end = range.end.clone();
1528                            }
1529
1530                            (
1531                                replica_id,
1532                                Selection {
1533                                    id: selection.id,
1534                                    start,
1535                                    end,
1536                                    reversed: selection.reversed,
1537                                    goal: selection.goal,
1538                                },
1539                            )
1540                        })
1541                    })
1542            })
1543    }
1544}
1545
1546impl History {
1547    fn start_transaction(&mut self, now: Instant) -> Option<TransactionId> {
1548        self.transaction_depth += 1;
1549        if self.transaction_depth == 1 {
1550            let id = post_inc(&mut self.next_transaction_id);
1551            self.undo_stack.push(Transaction {
1552                id,
1553                buffer_transactions: Default::default(),
1554                first_edit_at: now,
1555                last_edit_at: now,
1556            });
1557            Some(id)
1558        } else {
1559            None
1560        }
1561    }
1562
1563    fn end_transaction(
1564        &mut self,
1565        now: Instant,
1566        buffer_transactions: HashSet<(usize, TransactionId)>,
1567    ) -> bool {
1568        assert_ne!(self.transaction_depth, 0);
1569        self.transaction_depth -= 1;
1570        if self.transaction_depth == 0 {
1571            if buffer_transactions.is_empty() {
1572                self.undo_stack.pop();
1573                false
1574            } else {
1575                let transaction = self.undo_stack.last_mut().unwrap();
1576                transaction.last_edit_at = now;
1577                transaction.buffer_transactions.extend(buffer_transactions);
1578                true
1579            }
1580        } else {
1581            false
1582        }
1583    }
1584
1585    fn pop_undo(&mut self) -> Option<&Transaction> {
1586        assert_eq!(self.transaction_depth, 0);
1587        if let Some(transaction) = self.undo_stack.pop() {
1588            self.redo_stack.push(transaction);
1589            self.redo_stack.last()
1590        } else {
1591            None
1592        }
1593    }
1594
1595    fn pop_redo(&mut self) -> Option<&Transaction> {
1596        assert_eq!(self.transaction_depth, 0);
1597        if let Some(transaction) = self.redo_stack.pop() {
1598            self.undo_stack.push(transaction);
1599            self.undo_stack.last()
1600        } else {
1601            None
1602        }
1603    }
1604
1605    fn group(&mut self) -> Option<TransactionId> {
1606        let mut new_len = self.undo_stack.len();
1607        let mut transactions = self.undo_stack.iter_mut();
1608
1609        if let Some(mut transaction) = transactions.next_back() {
1610            while let Some(prev_transaction) = transactions.next_back() {
1611                if transaction.first_edit_at - prev_transaction.last_edit_at <= self.group_interval
1612                {
1613                    transaction = prev_transaction;
1614                    new_len -= 1;
1615                } else {
1616                    break;
1617                }
1618            }
1619        }
1620
1621        let (transactions_to_keep, transactions_to_merge) = self.undo_stack.split_at_mut(new_len);
1622        if let Some(last_transaction) = transactions_to_keep.last_mut() {
1623            if let Some(transaction) = transactions_to_merge.last() {
1624                last_transaction.last_edit_at = transaction.last_edit_at;
1625            }
1626        }
1627
1628        self.undo_stack.truncate(new_len);
1629        self.undo_stack.last().map(|t| t.id)
1630    }
1631}
1632
1633impl Excerpt {
1634    fn new(
1635        id: ExcerptId,
1636        buffer_id: usize,
1637        buffer: BufferSnapshot,
1638        range: Range<text::Anchor>,
1639        has_trailing_newline: bool,
1640    ) -> Self {
1641        Excerpt {
1642            id,
1643            max_buffer_row: range.end.to_point(&buffer).row,
1644            text_summary: buffer.text_summary_for_range::<TextSummary, _>(range.to_offset(&buffer)),
1645            buffer_id,
1646            buffer,
1647            range,
1648            has_trailing_newline,
1649        }
1650    }
1651
1652    fn chunks_in_range<'a>(
1653        &'a self,
1654        range: Range<usize>,
1655        theme: Option<&'a SyntaxTheme>,
1656    ) -> ExcerptChunks<'a> {
1657        let content_start = self.range.start.to_offset(&self.buffer);
1658        let chunks_start = content_start + range.start;
1659        let chunks_end = content_start + cmp::min(range.end, self.text_summary.bytes);
1660
1661        let footer_height = if self.has_trailing_newline
1662            && range.start <= self.text_summary.bytes
1663            && range.end > self.text_summary.bytes
1664        {
1665            1
1666        } else {
1667            0
1668        };
1669
1670        let content_chunks = self.buffer.chunks(chunks_start..chunks_end, theme);
1671
1672        ExcerptChunks {
1673            content_chunks,
1674            footer_height,
1675        }
1676    }
1677
1678    fn bytes_in_range(&self, range: Range<usize>) -> ExcerptBytes {
1679        let content_start = self.range.start.to_offset(&self.buffer);
1680        let bytes_start = content_start + range.start;
1681        let bytes_end = content_start + cmp::min(range.end, self.text_summary.bytes);
1682        let footer_height = if self.has_trailing_newline
1683            && range.start <= self.text_summary.bytes
1684            && range.end > self.text_summary.bytes
1685        {
1686            1
1687        } else {
1688            0
1689        };
1690        let content_bytes = self.buffer.bytes_in_range(bytes_start..bytes_end);
1691
1692        ExcerptBytes {
1693            content_bytes,
1694            footer_height,
1695        }
1696    }
1697
1698    fn clip_anchor(&self, text_anchor: text::Anchor) -> text::Anchor {
1699        if text_anchor
1700            .cmp(&self.range.start, &self.buffer)
1701            .unwrap()
1702            .is_lt()
1703        {
1704            self.range.start.clone()
1705        } else if text_anchor
1706            .cmp(&self.range.end, &self.buffer)
1707            .unwrap()
1708            .is_gt()
1709        {
1710            self.range.end.clone()
1711        } else {
1712            text_anchor
1713        }
1714    }
1715}
1716
1717impl fmt::Debug for Excerpt {
1718    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1719        f.debug_struct("Excerpt")
1720            .field("id", &self.id)
1721            .field("buffer_id", &self.buffer_id)
1722            .field("range", &self.range)
1723            .field("text_summary", &self.text_summary)
1724            .field("has_trailing_newline", &self.has_trailing_newline)
1725            .finish()
1726    }
1727}
1728
1729impl sum_tree::Item for Excerpt {
1730    type Summary = ExcerptSummary;
1731
1732    fn summary(&self) -> Self::Summary {
1733        let mut text = self.text_summary.clone();
1734        if self.has_trailing_newline {
1735            text += TextSummary::from("\n");
1736        }
1737        ExcerptSummary {
1738            excerpt_id: self.id.clone(),
1739            max_buffer_row: self.max_buffer_row,
1740            text,
1741        }
1742    }
1743}
1744
1745impl sum_tree::Summary for ExcerptSummary {
1746    type Context = ();
1747
1748    fn add_summary(&mut self, summary: &Self, _: &()) {
1749        debug_assert!(summary.excerpt_id > self.excerpt_id);
1750        self.excerpt_id = summary.excerpt_id.clone();
1751        self.text.add_summary(&summary.text, &());
1752        self.max_buffer_row = cmp::max(self.max_buffer_row, summary.max_buffer_row);
1753    }
1754}
1755
1756impl<'a> sum_tree::Dimension<'a, ExcerptSummary> for TextSummary {
1757    fn add_summary(&mut self, summary: &'a ExcerptSummary, _: &()) {
1758        *self += &summary.text;
1759    }
1760}
1761
1762impl<'a> sum_tree::Dimension<'a, ExcerptSummary> for usize {
1763    fn add_summary(&mut self, summary: &'a ExcerptSummary, _: &()) {
1764        *self += summary.text.bytes;
1765    }
1766}
1767
1768impl<'a> sum_tree::SeekTarget<'a, ExcerptSummary, ExcerptSummary> for usize {
1769    fn cmp(&self, cursor_location: &ExcerptSummary, _: &()) -> cmp::Ordering {
1770        Ord::cmp(self, &cursor_location.text.bytes)
1771    }
1772}
1773
1774impl<'a> sum_tree::SeekTarget<'a, ExcerptSummary, ExcerptSummary> for Option<&'a ExcerptId> {
1775    fn cmp(&self, cursor_location: &ExcerptSummary, _: &()) -> cmp::Ordering {
1776        Ord::cmp(self, &Some(&cursor_location.excerpt_id))
1777    }
1778}
1779
1780impl<'a> sum_tree::Dimension<'a, ExcerptSummary> for Point {
1781    fn add_summary(&mut self, summary: &'a ExcerptSummary, _: &()) {
1782        *self += summary.text.lines;
1783    }
1784}
1785
1786impl<'a> sum_tree::Dimension<'a, ExcerptSummary> for PointUtf16 {
1787    fn add_summary(&mut self, summary: &'a ExcerptSummary, _: &()) {
1788        *self += summary.text.lines_utf16
1789    }
1790}
1791
1792impl<'a> sum_tree::Dimension<'a, ExcerptSummary> for Option<&'a ExcerptId> {
1793    fn add_summary(&mut self, summary: &'a ExcerptSummary, _: &()) {
1794        *self = Some(&summary.excerpt_id);
1795    }
1796}
1797
1798impl<'a> MultiBufferRows<'a> {
1799    pub fn seek(&mut self, row: u32) {
1800        self.buffer_row_range = 0..0;
1801
1802        self.excerpts
1803            .seek_forward(&Point::new(row, 0), Bias::Right, &());
1804        if self.excerpts.item().is_none() {
1805            self.excerpts.prev(&());
1806
1807            if self.excerpts.item().is_none() && row == 0 {
1808                self.buffer_row_range = 0..1;
1809                return;
1810            }
1811        }
1812
1813        if let Some(excerpt) = self.excerpts.item() {
1814            let overshoot = row - self.excerpts.start().row;
1815            let excerpt_start = excerpt.range.start.to_point(&excerpt.buffer).row;
1816            self.buffer_row_range.start = excerpt_start + overshoot;
1817            self.buffer_row_range.end = excerpt_start + excerpt.text_summary.lines.row + 1;
1818        }
1819    }
1820}
1821
1822impl<'a> Iterator for MultiBufferRows<'a> {
1823    type Item = Option<u32>;
1824
1825    fn next(&mut self) -> Option<Self::Item> {
1826        loop {
1827            if !self.buffer_row_range.is_empty() {
1828                let row = Some(self.buffer_row_range.start);
1829                self.buffer_row_range.start += 1;
1830                return Some(row);
1831            }
1832            self.excerpts.item()?;
1833            self.excerpts.next(&());
1834            let excerpt = self.excerpts.item()?;
1835            self.buffer_row_range.start = excerpt.range.start.to_point(&excerpt.buffer).row;
1836            self.buffer_row_range.end =
1837                self.buffer_row_range.start + excerpt.text_summary.lines.row + 1;
1838        }
1839    }
1840}
1841
1842impl<'a> MultiBufferChunks<'a> {
1843    pub fn offset(&self) -> usize {
1844        self.range.start
1845    }
1846
1847    pub fn seek(&mut self, offset: usize) {
1848        self.range.start = offset;
1849        self.excerpts.seek(&offset, Bias::Right, &());
1850        if let Some(excerpt) = self.excerpts.item() {
1851            self.excerpt_chunks = Some(excerpt.chunks_in_range(
1852                self.range.start - self.excerpts.start()..self.range.end - self.excerpts.start(),
1853                self.theme,
1854            ));
1855        } else {
1856            self.excerpt_chunks = None;
1857        }
1858    }
1859}
1860
1861impl<'a> Iterator for MultiBufferChunks<'a> {
1862    type Item = Chunk<'a>;
1863
1864    fn next(&mut self) -> Option<Self::Item> {
1865        if self.range.is_empty() {
1866            None
1867        } else if let Some(chunk) = self.excerpt_chunks.as_mut()?.next() {
1868            self.range.start += chunk.text.len();
1869            Some(chunk)
1870        } else {
1871            self.excerpts.next(&());
1872            let excerpt = self.excerpts.item()?;
1873            self.excerpt_chunks = Some(
1874                excerpt.chunks_in_range(0..self.range.end - self.excerpts.start(), self.theme),
1875            );
1876            self.next()
1877        }
1878    }
1879}
1880
1881impl<'a> MultiBufferBytes<'a> {
1882    fn consume(&mut self, len: usize) {
1883        self.range.start += len;
1884        self.chunk = &self.chunk[len..];
1885
1886        if !self.range.is_empty() && self.chunk.is_empty() {
1887            if let Some(chunk) = self.excerpt_bytes.as_mut().and_then(|bytes| bytes.next()) {
1888                self.chunk = chunk;
1889            } else {
1890                self.excerpts.next(&());
1891                if let Some(excerpt) = self.excerpts.item() {
1892                    let mut excerpt_bytes =
1893                        excerpt.bytes_in_range(0..self.range.end - self.excerpts.start());
1894                    self.chunk = excerpt_bytes.next().unwrap();
1895                    self.excerpt_bytes = Some(excerpt_bytes);
1896                }
1897            }
1898        }
1899    }
1900}
1901
1902impl<'a> Iterator for MultiBufferBytes<'a> {
1903    type Item = &'a [u8];
1904
1905    fn next(&mut self) -> Option<Self::Item> {
1906        let chunk = self.chunk;
1907        if chunk.is_empty() {
1908            None
1909        } else {
1910            self.consume(chunk.len());
1911            Some(chunk)
1912        }
1913    }
1914}
1915
1916impl<'a> io::Read for MultiBufferBytes<'a> {
1917    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
1918        let len = cmp::min(buf.len(), self.chunk.len());
1919        buf[..len].copy_from_slice(&self.chunk[..len]);
1920        if len > 0 {
1921            self.consume(len);
1922        }
1923        Ok(len)
1924    }
1925}
1926
1927impl<'a> Iterator for ExcerptBytes<'a> {
1928    type Item = &'a [u8];
1929
1930    fn next(&mut self) -> Option<Self::Item> {
1931        if let Some(chunk) = self.content_bytes.next() {
1932            if !chunk.is_empty() {
1933                return Some(chunk);
1934            }
1935        }
1936
1937        if self.footer_height > 0 {
1938            let result = &NEWLINES[..self.footer_height];
1939            self.footer_height = 0;
1940            return Some(result);
1941        }
1942
1943        None
1944    }
1945}
1946
1947impl<'a> Iterator for ExcerptChunks<'a> {
1948    type Item = Chunk<'a>;
1949
1950    fn next(&mut self) -> Option<Self::Item> {
1951        if let Some(chunk) = self.content_chunks.next() {
1952            return Some(chunk);
1953        }
1954
1955        if self.footer_height > 0 {
1956            let text = unsafe { str::from_utf8_unchecked(&NEWLINES[..self.footer_height]) };
1957            self.footer_height = 0;
1958            return Some(Chunk {
1959                text,
1960                ..Default::default()
1961            });
1962        }
1963
1964        None
1965    }
1966}
1967
1968impl ToOffset for Point {
1969    fn to_offset<'a>(&self, snapshot: &MultiBufferSnapshot) -> usize {
1970        snapshot.point_to_offset(*self)
1971    }
1972}
1973
1974impl ToOffset for PointUtf16 {
1975    fn to_offset<'a>(&self, snapshot: &MultiBufferSnapshot) -> usize {
1976        snapshot.point_utf16_to_offset(*self)
1977    }
1978}
1979
1980impl ToOffset for usize {
1981    fn to_offset<'a>(&self, snapshot: &MultiBufferSnapshot) -> usize {
1982        assert!(*self <= snapshot.len(), "offset is out of range");
1983        *self
1984    }
1985}
1986
1987impl ToPoint for usize {
1988    fn to_point<'a>(&self, snapshot: &MultiBufferSnapshot) -> Point {
1989        snapshot.offset_to_point(*self)
1990    }
1991}
1992
1993impl ToPoint for Point {
1994    fn to_point<'a>(&self, _: &MultiBufferSnapshot) -> Point {
1995        *self
1996    }
1997}
1998
1999#[cfg(test)]
2000mod tests {
2001    use super::*;
2002    use gpui::MutableAppContext;
2003    use language::{Buffer, Rope};
2004    use rand::prelude::*;
2005    use std::env;
2006    use text::{Point, RandomCharIter};
2007    use util::test::sample_text;
2008
2009    #[gpui::test]
2010    fn test_singleton_multibuffer(cx: &mut MutableAppContext) {
2011        let buffer = cx.add_model(|cx| Buffer::new(0, sample_text(6, 6, 'a'), cx));
2012        let multibuffer = cx.add_model(|cx| MultiBuffer::singleton(buffer.clone(), cx));
2013
2014        let snapshot = multibuffer.read(cx).snapshot(cx);
2015        assert_eq!(snapshot.text(), buffer.read(cx).text());
2016
2017        assert_eq!(
2018            snapshot.buffer_rows(0).collect::<Vec<_>>(),
2019            (0..buffer.read(cx).row_count())
2020                .map(Some)
2021                .collect::<Vec<_>>()
2022        );
2023
2024        buffer.update(cx, |buffer, cx| buffer.edit([1..3], "XXX\n", cx));
2025        let snapshot = multibuffer.read(cx).snapshot(cx);
2026
2027        assert_eq!(snapshot.text(), buffer.read(cx).text());
2028        assert_eq!(
2029            snapshot.buffer_rows(0).collect::<Vec<_>>(),
2030            (0..buffer.read(cx).row_count())
2031                .map(Some)
2032                .collect::<Vec<_>>()
2033        );
2034    }
2035
2036    #[gpui::test]
2037    fn test_excerpt_buffer(cx: &mut MutableAppContext) {
2038        let buffer_1 = cx.add_model(|cx| Buffer::new(0, sample_text(6, 6, 'a'), cx));
2039        let buffer_2 = cx.add_model(|cx| Buffer::new(0, sample_text(6, 6, 'g'), cx));
2040        let multibuffer = cx.add_model(|_| MultiBuffer::new(0));
2041
2042        let subscription = multibuffer.update(cx, |multibuffer, cx| {
2043            let subscription = multibuffer.subscribe();
2044            multibuffer.push_excerpt(
2045                ExcerptProperties {
2046                    buffer: &buffer_1,
2047                    range: Point::new(1, 2)..Point::new(2, 5),
2048                },
2049                cx,
2050            );
2051            assert_eq!(
2052                subscription.consume().into_inner(),
2053                [Edit {
2054                    old: 0..0,
2055                    new: 0..10
2056                }]
2057            );
2058
2059            multibuffer.push_excerpt(
2060                ExcerptProperties {
2061                    buffer: &buffer_1,
2062                    range: Point::new(3, 3)..Point::new(4, 4),
2063                },
2064                cx,
2065            );
2066            multibuffer.push_excerpt(
2067                ExcerptProperties {
2068                    buffer: &buffer_2,
2069                    range: Point::new(3, 1)..Point::new(3, 3),
2070                },
2071                cx,
2072            );
2073            assert_eq!(
2074                subscription.consume().into_inner(),
2075                [Edit {
2076                    old: 10..10,
2077                    new: 10..22
2078                }]
2079            );
2080
2081            subscription
2082        });
2083
2084        let snapshot = multibuffer.read(cx).snapshot(cx);
2085        assert_eq!(
2086            snapshot.text(),
2087            concat!(
2088                "bbbb\n",  // Preserve newlines
2089                "ccccc\n", //
2090                "ddd\n",   //
2091                "eeee\n",  //
2092                "jj"       //
2093            )
2094        );
2095        assert_eq!(
2096            snapshot.buffer_rows(0).collect::<Vec<_>>(),
2097            [Some(1), Some(2), Some(3), Some(4), Some(3)]
2098        );
2099        assert_eq!(
2100            snapshot.buffer_rows(2).collect::<Vec<_>>(),
2101            [Some(3), Some(4), Some(3)]
2102        );
2103        assert_eq!(snapshot.buffer_rows(4).collect::<Vec<_>>(), [Some(3)]);
2104        assert_eq!(snapshot.buffer_rows(5).collect::<Vec<_>>(), []);
2105
2106        buffer_1.update(cx, |buffer, cx| {
2107            buffer.edit(
2108                [
2109                    Point::new(0, 0)..Point::new(0, 0),
2110                    Point::new(2, 1)..Point::new(2, 3),
2111                ],
2112                "\n",
2113                cx,
2114            );
2115        });
2116
2117        let snapshot = multibuffer.read(cx).snapshot(cx);
2118        assert_eq!(
2119            snapshot.text(),
2120            concat!(
2121                "bbbb\n", // Preserve newlines
2122                "c\n",    //
2123                "cc\n",   //
2124                "ddd\n",  //
2125                "eeee\n", //
2126                "jj"      //
2127            )
2128        );
2129
2130        assert_eq!(
2131            subscription.consume().into_inner(),
2132            [Edit {
2133                old: 6..8,
2134                new: 6..7
2135            }]
2136        );
2137
2138        let snapshot = multibuffer.read(cx).snapshot(cx);
2139        assert_eq!(
2140            snapshot.clip_point(Point::new(0, 5), Bias::Left),
2141            Point::new(0, 4)
2142        );
2143        assert_eq!(
2144            snapshot.clip_point(Point::new(0, 5), Bias::Right),
2145            Point::new(0, 4)
2146        );
2147        assert_eq!(
2148            snapshot.clip_point(Point::new(5, 1), Bias::Right),
2149            Point::new(5, 1)
2150        );
2151        assert_eq!(
2152            snapshot.clip_point(Point::new(5, 2), Bias::Right),
2153            Point::new(5, 2)
2154        );
2155        assert_eq!(
2156            snapshot.clip_point(Point::new(5, 3), Bias::Right),
2157            Point::new(5, 2)
2158        );
2159
2160        let snapshot = multibuffer.update(cx, |multibuffer, cx| {
2161            let buffer_2_excerpt_id = multibuffer.excerpt_ids_for_buffer(&buffer_2)[0].clone();
2162            multibuffer.remove_excerpts(&[buffer_2_excerpt_id], cx);
2163            multibuffer.snapshot(cx)
2164        });
2165
2166        assert_eq!(
2167            snapshot.text(),
2168            concat!(
2169                "bbbb\n", // Preserve newlines
2170                "c\n",    //
2171                "cc\n",   //
2172                "ddd\n",  //
2173                "eeee",   //
2174            )
2175        );
2176    }
2177
2178    #[gpui::test]
2179    fn test_empty_excerpt_buffer(cx: &mut MutableAppContext) {
2180        let multibuffer = cx.add_model(|_| MultiBuffer::new(0));
2181
2182        let snapshot = multibuffer.read(cx).snapshot(cx);
2183        assert_eq!(snapshot.text(), "");
2184        assert_eq!(snapshot.buffer_rows(0).collect::<Vec<_>>(), &[Some(0)]);
2185        assert_eq!(snapshot.buffer_rows(1).collect::<Vec<_>>(), &[]);
2186    }
2187
2188    #[gpui::test]
2189    fn test_singleton_multibuffer_anchors(cx: &mut MutableAppContext) {
2190        let buffer = cx.add_model(|cx| Buffer::new(0, "abcd", cx));
2191        let multibuffer = cx.add_model(|cx| MultiBuffer::singleton(buffer.clone(), cx));
2192        let old_snapshot = multibuffer.read(cx).snapshot(cx);
2193        buffer.update(cx, |buffer, cx| {
2194            buffer.edit([0..0], "X", cx);
2195            buffer.edit([5..5], "Y", cx);
2196        });
2197        let new_snapshot = multibuffer.read(cx).snapshot(cx);
2198
2199        assert_eq!(old_snapshot.text(), "abcd");
2200        assert_eq!(new_snapshot.text(), "XabcdY");
2201
2202        assert_eq!(old_snapshot.anchor_before(0).to_offset(&new_snapshot), 0);
2203        assert_eq!(old_snapshot.anchor_after(0).to_offset(&new_snapshot), 1);
2204        assert_eq!(old_snapshot.anchor_before(4).to_offset(&new_snapshot), 5);
2205        assert_eq!(old_snapshot.anchor_after(4).to_offset(&new_snapshot), 6);
2206    }
2207
2208    #[gpui::test]
2209    fn test_multibuffer_anchors(cx: &mut MutableAppContext) {
2210        let buffer_1 = cx.add_model(|cx| Buffer::new(0, "abcd", cx));
2211        let buffer_2 = cx.add_model(|cx| Buffer::new(0, "efghi", cx));
2212        let multibuffer = cx.add_model(|cx| {
2213            let mut multibuffer = MultiBuffer::new(0);
2214            multibuffer.push_excerpt(
2215                ExcerptProperties {
2216                    buffer: &buffer_1,
2217                    range: 0..4,
2218                },
2219                cx,
2220            );
2221            multibuffer.push_excerpt(
2222                ExcerptProperties {
2223                    buffer: &buffer_2,
2224                    range: 0..5,
2225                },
2226                cx,
2227            );
2228            multibuffer
2229        });
2230        let old_snapshot = multibuffer.read(cx).snapshot(cx);
2231
2232        assert_eq!(old_snapshot.anchor_before(0).to_offset(&old_snapshot), 0);
2233        assert_eq!(old_snapshot.anchor_after(0).to_offset(&old_snapshot), 0);
2234        assert_eq!(Anchor::min().to_offset(&old_snapshot), 0);
2235        assert_eq!(Anchor::min().to_offset(&old_snapshot), 0);
2236        assert_eq!(Anchor::max().to_offset(&old_snapshot), 10);
2237        assert_eq!(Anchor::max().to_offset(&old_snapshot), 10);
2238
2239        buffer_1.update(cx, |buffer, cx| {
2240            buffer.edit([0..0], "W", cx);
2241            buffer.edit([5..5], "X", cx);
2242        });
2243        buffer_2.update(cx, |buffer, cx| {
2244            buffer.edit([0..0], "Y", cx);
2245            buffer.edit([6..0], "Z", cx);
2246        });
2247        let new_snapshot = multibuffer.read(cx).snapshot(cx);
2248
2249        assert_eq!(old_snapshot.text(), "abcd\nefghi");
2250        assert_eq!(new_snapshot.text(), "WabcdX\nYefghiZ");
2251
2252        assert_eq!(old_snapshot.anchor_before(0).to_offset(&new_snapshot), 0);
2253        assert_eq!(old_snapshot.anchor_after(0).to_offset(&new_snapshot), 1);
2254        assert_eq!(old_snapshot.anchor_before(1).to_offset(&new_snapshot), 2);
2255        assert_eq!(old_snapshot.anchor_after(1).to_offset(&new_snapshot), 2);
2256        assert_eq!(old_snapshot.anchor_before(2).to_offset(&new_snapshot), 3);
2257        assert_eq!(old_snapshot.anchor_after(2).to_offset(&new_snapshot), 3);
2258        assert_eq!(old_snapshot.anchor_before(5).to_offset(&new_snapshot), 7);
2259        assert_eq!(old_snapshot.anchor_after(5).to_offset(&new_snapshot), 8);
2260        assert_eq!(old_snapshot.anchor_before(10).to_offset(&new_snapshot), 13);
2261        assert_eq!(old_snapshot.anchor_after(10).to_offset(&new_snapshot), 14);
2262    }
2263
2264    #[gpui::test(iterations = 100)]
2265    fn test_random_excerpts(cx: &mut MutableAppContext, mut rng: StdRng) {
2266        let operations = env::var("OPERATIONS")
2267            .map(|i| i.parse().expect("invalid `OPERATIONS` variable"))
2268            .unwrap_or(10);
2269
2270        let mut buffers: Vec<ModelHandle<Buffer>> = Vec::new();
2271        let list = cx.add_model(|_| MultiBuffer::new(0));
2272        let mut excerpt_ids = Vec::new();
2273        let mut expected_excerpts = Vec::<(ModelHandle<Buffer>, Range<text::Anchor>)>::new();
2274        let mut old_versions = Vec::new();
2275
2276        for _ in 0..operations {
2277            match rng.gen_range(0..100) {
2278                0..=19 if !buffers.is_empty() => {
2279                    let buffer = buffers.choose(&mut rng).unwrap();
2280                    buffer.update(cx, |buf, cx| buf.randomly_edit(&mut rng, 5, cx));
2281                }
2282                20..=29 if !expected_excerpts.is_empty() => {
2283                    let ix = rng.gen_range(0..expected_excerpts.len());
2284                    let id = excerpt_ids.remove(ix);
2285                    let (buffer, range) = expected_excerpts.remove(ix);
2286                    let buffer = buffer.read(cx);
2287                    log::info!(
2288                        "Removing excerpt {}: {:?}",
2289                        ix,
2290                        buffer
2291                            .text_for_range(range.to_offset(&buffer))
2292                            .collect::<String>(),
2293                    );
2294                    list.update(cx, |list, cx| list.remove_excerpts(&[id], cx));
2295                }
2296                _ => {
2297                    let buffer_handle = if buffers.is_empty() || rng.gen_bool(0.4) {
2298                        let base_text = RandomCharIter::new(&mut rng).take(10).collect::<String>();
2299                        buffers.push(cx.add_model(|cx| Buffer::new(0, base_text, cx)));
2300                        buffers.last().unwrap()
2301                    } else {
2302                        buffers.choose(&mut rng).unwrap()
2303                    };
2304
2305                    let buffer = buffer_handle.read(cx);
2306                    let end_ix = buffer.clip_offset(rng.gen_range(0..=buffer.len()), Bias::Right);
2307                    let start_ix = buffer.clip_offset(rng.gen_range(0..=end_ix), Bias::Left);
2308                    let anchor_range = buffer.anchor_before(start_ix)..buffer.anchor_after(end_ix);
2309                    log::info!(
2310                        "Pushing excerpt for buffer {}: {:?}[{:?}] = {:?}",
2311                        buffer_handle.id(),
2312                        buffer.text(),
2313                        start_ix..end_ix,
2314                        &buffer.text()[start_ix..end_ix]
2315                    );
2316
2317                    let excerpt_id = list.update(cx, |list, cx| {
2318                        list.push_excerpt(
2319                            ExcerptProperties {
2320                                buffer: &buffer_handle,
2321                                range: start_ix..end_ix,
2322                            },
2323                            cx,
2324                        )
2325                    });
2326                    excerpt_ids.push(excerpt_id);
2327                    expected_excerpts.push((buffer_handle.clone(), anchor_range));
2328                }
2329            }
2330
2331            if rng.gen_bool(0.3) {
2332                list.update(cx, |list, cx| {
2333                    old_versions.push((list.snapshot(cx), list.subscribe()));
2334                })
2335            }
2336
2337            let snapshot = list.read(cx).snapshot(cx);
2338
2339            let mut excerpt_starts = Vec::new();
2340            let mut expected_text = String::new();
2341            let mut expected_buffer_rows = Vec::new();
2342            for (buffer, range) in &expected_excerpts {
2343                let buffer = buffer.read(cx);
2344                let buffer_range = range.to_offset(buffer);
2345
2346                excerpt_starts.push(TextSummary::from(expected_text.as_str()));
2347                expected_text.extend(buffer.text_for_range(buffer_range.clone()));
2348                expected_text.push('\n');
2349
2350                let buffer_row_range = buffer.offset_to_point(buffer_range.start).row
2351                    ..=buffer.offset_to_point(buffer_range.end).row;
2352                for row in buffer_row_range {
2353                    expected_buffer_rows.push(Some(row));
2354                }
2355            }
2356            // Remove final trailing newline.
2357            if !expected_excerpts.is_empty() {
2358                expected_text.pop();
2359            }
2360
2361            // Always report one buffer row
2362            if expected_buffer_rows.is_empty() {
2363                expected_buffer_rows.push(Some(0));
2364            }
2365
2366            assert_eq!(snapshot.text(), expected_text);
2367            log::info!("MultiBuffer text: {:?}", expected_text);
2368
2369            assert_eq!(
2370                snapshot.buffer_rows(0).collect::<Vec<_>>(),
2371                expected_buffer_rows,
2372            );
2373
2374            for _ in 0..5 {
2375                let start_row = rng.gen_range(0..=expected_buffer_rows.len());
2376                assert_eq!(
2377                    snapshot.buffer_rows(start_row as u32).collect::<Vec<_>>(),
2378                    &expected_buffer_rows[start_row..],
2379                    "buffer_rows({})",
2380                    start_row
2381                );
2382            }
2383
2384            assert_eq!(
2385                snapshot.max_buffer_row(),
2386                expected_buffer_rows
2387                    .into_iter()
2388                    .filter_map(|r| r)
2389                    .max()
2390                    .unwrap()
2391            );
2392
2393            let mut excerpt_starts = excerpt_starts.into_iter();
2394            for (buffer, range) in &expected_excerpts {
2395                let buffer_id = buffer.id();
2396                let buffer = buffer.read(cx);
2397                let buffer_range = range.to_offset(buffer);
2398                let buffer_start_point = buffer.offset_to_point(buffer_range.start);
2399                let buffer_start_point_utf16 =
2400                    buffer.text_summary_for_range::<PointUtf16, _>(0..buffer_range.start);
2401
2402                let excerpt_start = excerpt_starts.next().unwrap();
2403                let mut offset = excerpt_start.bytes;
2404                let mut buffer_offset = buffer_range.start;
2405                let mut point = excerpt_start.lines;
2406                let mut buffer_point = buffer_start_point;
2407                let mut point_utf16 = excerpt_start.lines_utf16;
2408                let mut buffer_point_utf16 = buffer_start_point_utf16;
2409                for ch in buffer
2410                    .snapshot()
2411                    .chunks(buffer_range.clone(), None)
2412                    .flat_map(|c| c.text.chars())
2413                {
2414                    for _ in 0..ch.len_utf8() {
2415                        let left_offset = snapshot.clip_offset(offset, Bias::Left);
2416                        let right_offset = snapshot.clip_offset(offset, Bias::Right);
2417                        let buffer_left_offset = buffer.clip_offset(buffer_offset, Bias::Left);
2418                        let buffer_right_offset = buffer.clip_offset(buffer_offset, Bias::Right);
2419                        assert_eq!(
2420                            left_offset,
2421                            excerpt_start.bytes + (buffer_left_offset - buffer_range.start),
2422                            "clip_offset({:?}, Left). buffer: {:?}, buffer offset: {:?}",
2423                            offset,
2424                            buffer_id,
2425                            buffer_offset,
2426                        );
2427                        assert_eq!(
2428                            right_offset,
2429                            excerpt_start.bytes + (buffer_right_offset - buffer_range.start),
2430                            "clip_offset({:?}, Right). buffer: {:?}, buffer offset: {:?}",
2431                            offset,
2432                            buffer_id,
2433                            buffer_offset,
2434                        );
2435
2436                        let left_point = snapshot.clip_point(point, Bias::Left);
2437                        let right_point = snapshot.clip_point(point, Bias::Right);
2438                        let buffer_left_point = buffer.clip_point(buffer_point, Bias::Left);
2439                        let buffer_right_point = buffer.clip_point(buffer_point, Bias::Right);
2440                        assert_eq!(
2441                            left_point,
2442                            excerpt_start.lines + (buffer_left_point - buffer_start_point),
2443                            "clip_point({:?}, Left). buffer: {:?}, buffer point: {:?}",
2444                            point,
2445                            buffer_id,
2446                            buffer_point,
2447                        );
2448                        assert_eq!(
2449                            right_point,
2450                            excerpt_start.lines + (buffer_right_point - buffer_start_point),
2451                            "clip_point({:?}, Right). buffer: {:?}, buffer point: {:?}",
2452                            point,
2453                            buffer_id,
2454                            buffer_point,
2455                        );
2456
2457                        assert_eq!(
2458                            snapshot.point_to_offset(left_point),
2459                            left_offset,
2460                            "point_to_offset({:?})",
2461                            left_point,
2462                        );
2463                        assert_eq!(
2464                            snapshot.offset_to_point(left_offset),
2465                            left_point,
2466                            "offset_to_point({:?})",
2467                            left_offset,
2468                        );
2469
2470                        offset += 1;
2471                        buffer_offset += 1;
2472                        if ch == '\n' {
2473                            point += Point::new(1, 0);
2474                            buffer_point += Point::new(1, 0);
2475                        } else {
2476                            point += Point::new(0, 1);
2477                            buffer_point += Point::new(0, 1);
2478                        }
2479                    }
2480
2481                    for _ in 0..ch.len_utf16() {
2482                        let left_point_utf16 = snapshot.clip_point_utf16(point_utf16, Bias::Left);
2483                        let right_point_utf16 = snapshot.clip_point_utf16(point_utf16, Bias::Right);
2484                        let buffer_left_point_utf16 =
2485                            buffer.clip_point_utf16(buffer_point_utf16, Bias::Left);
2486                        let buffer_right_point_utf16 =
2487                            buffer.clip_point_utf16(buffer_point_utf16, Bias::Right);
2488                        assert_eq!(
2489                            left_point_utf16,
2490                            excerpt_start.lines_utf16
2491                                + (buffer_left_point_utf16 - buffer_start_point_utf16),
2492                            "clip_point_utf16({:?}, Left). buffer: {:?}, buffer point_utf16: {:?}",
2493                            point_utf16,
2494                            buffer_id,
2495                            buffer_point_utf16,
2496                        );
2497                        assert_eq!(
2498                            right_point_utf16,
2499                            excerpt_start.lines_utf16
2500                                + (buffer_right_point_utf16 - buffer_start_point_utf16),
2501                            "clip_point_utf16({:?}, Right). buffer: {:?}, buffer point_utf16: {:?}",
2502                            point_utf16,
2503                            buffer_id,
2504                            buffer_point_utf16,
2505                        );
2506
2507                        if ch == '\n' {
2508                            point_utf16 += PointUtf16::new(1, 0);
2509                            buffer_point_utf16 += PointUtf16::new(1, 0);
2510                        } else {
2511                            point_utf16 += PointUtf16::new(0, 1);
2512                            buffer_point_utf16 += PointUtf16::new(0, 1);
2513                        }
2514                    }
2515                }
2516            }
2517
2518            for (row, line) in expected_text.split('\n').enumerate() {
2519                assert_eq!(
2520                    snapshot.line_len(row as u32),
2521                    line.len() as u32,
2522                    "line_len({}).",
2523                    row
2524                );
2525            }
2526
2527            let text_rope = Rope::from(expected_text.as_str());
2528            for _ in 0..10 {
2529                let end_ix = text_rope.clip_offset(rng.gen_range(0..=text_rope.len()), Bias::Right);
2530                let start_ix = text_rope.clip_offset(rng.gen_range(0..=end_ix), Bias::Left);
2531
2532                assert_eq!(
2533                    snapshot
2534                        .text_for_range(start_ix..end_ix)
2535                        .collect::<String>(),
2536                    &expected_text[start_ix..end_ix],
2537                    "incorrect text for range {:?}",
2538                    start_ix..end_ix
2539                );
2540
2541                let expected_summary = TextSummary::from(&expected_text[start_ix..end_ix]);
2542                assert_eq!(
2543                    snapshot.text_summary_for_range::<TextSummary, _>(start_ix..end_ix),
2544                    expected_summary,
2545                    "incorrect summary for range {:?}",
2546                    start_ix..end_ix
2547                );
2548            }
2549
2550            for _ in 0..10 {
2551                let end_ix = text_rope.clip_offset(rng.gen_range(0..=text_rope.len()), Bias::Right);
2552                assert_eq!(
2553                    snapshot.reversed_chars_at(end_ix).collect::<String>(),
2554                    expected_text[..end_ix].chars().rev().collect::<String>(),
2555                );
2556            }
2557
2558            for _ in 0..10 {
2559                let end_ix = rng.gen_range(0..=text_rope.len());
2560                let start_ix = rng.gen_range(0..=end_ix);
2561                assert_eq!(
2562                    snapshot
2563                        .bytes_in_range(start_ix..end_ix)
2564                        .flatten()
2565                        .copied()
2566                        .collect::<Vec<_>>(),
2567                    expected_text.as_bytes()[start_ix..end_ix].to_vec(),
2568                    "bytes_in_range({:?})",
2569                    start_ix..end_ix,
2570                );
2571            }
2572        }
2573
2574        let snapshot = list.read(cx).snapshot(cx);
2575        for (old_snapshot, subscription) in old_versions {
2576            let edits = subscription.consume().into_inner();
2577
2578            log::info!(
2579                "applying subscription edits to old text: {:?}: {:?}",
2580                old_snapshot.text(),
2581                edits,
2582            );
2583
2584            let mut text = old_snapshot.text();
2585            for edit in edits {
2586                let new_text: String = snapshot.text_for_range(edit.new.clone()).collect();
2587                text.replace_range(edit.new.start..edit.new.start + edit.old.len(), &new_text);
2588            }
2589            assert_eq!(text.to_string(), snapshot.text());
2590        }
2591    }
2592
2593    #[gpui::test]
2594    fn test_history(cx: &mut MutableAppContext) {
2595        let buffer_1 = cx.add_model(|cx| Buffer::new(0, "1234", cx));
2596        let buffer_2 = cx.add_model(|cx| Buffer::new(0, "5678", cx));
2597        let multibuffer = cx.add_model(|_| MultiBuffer::new(0));
2598        let group_interval = multibuffer.read(cx).history.group_interval;
2599        multibuffer.update(cx, |multibuffer, cx| {
2600            multibuffer.push_excerpt(
2601                ExcerptProperties {
2602                    buffer: &buffer_1,
2603                    range: 0..buffer_1.read(cx).len(),
2604                },
2605                cx,
2606            );
2607            multibuffer.push_excerpt(
2608                ExcerptProperties {
2609                    buffer: &buffer_2,
2610                    range: 0..buffer_2.read(cx).len(),
2611                },
2612                cx,
2613            );
2614        });
2615
2616        let mut now = Instant::now();
2617
2618        multibuffer.update(cx, |multibuffer, cx| {
2619            multibuffer.start_transaction_at(now, cx);
2620            multibuffer.edit(
2621                [
2622                    Point::new(0, 0)..Point::new(0, 0),
2623                    Point::new(1, 0)..Point::new(1, 0),
2624                ],
2625                "A",
2626                cx,
2627            );
2628            multibuffer.edit(
2629                [
2630                    Point::new(0, 1)..Point::new(0, 1),
2631                    Point::new(1, 1)..Point::new(1, 1),
2632                ],
2633                "B",
2634                cx,
2635            );
2636            multibuffer.end_transaction_at(now, cx);
2637            assert_eq!(multibuffer.read(cx).text(), "AB1234\nAB5678");
2638
2639            now += 2 * group_interval;
2640            multibuffer.start_transaction_at(now, cx);
2641            multibuffer.edit([2..2], "C", cx);
2642            multibuffer.end_transaction_at(now, cx);
2643            assert_eq!(multibuffer.read(cx).text(), "ABC1234\nAB5678");
2644
2645            multibuffer.undo(cx);
2646            assert_eq!(multibuffer.read(cx).text(), "AB1234\nAB5678");
2647
2648            multibuffer.undo(cx);
2649            assert_eq!(multibuffer.read(cx).text(), "1234\n5678");
2650
2651            multibuffer.redo(cx);
2652            assert_eq!(multibuffer.read(cx).text(), "AB1234\nAB5678");
2653
2654            multibuffer.redo(cx);
2655            assert_eq!(multibuffer.read(cx).text(), "ABC1234\nAB5678");
2656
2657            buffer_1.update(cx, |buffer_1, cx| buffer_1.undo(cx));
2658            assert_eq!(multibuffer.read(cx).text(), "AB1234\nAB5678");
2659
2660            multibuffer.undo(cx);
2661            assert_eq!(multibuffer.read(cx).text(), "1234\n5678");
2662
2663            multibuffer.redo(cx);
2664            assert_eq!(multibuffer.read(cx).text(), "AB1234\nAB5678");
2665
2666            multibuffer.redo(cx);
2667            assert_eq!(multibuffer.read(cx).text(), "ABC1234\nAB5678");
2668
2669            multibuffer.undo(cx);
2670            assert_eq!(multibuffer.read(cx).text(), "AB1234\nAB5678");
2671
2672            buffer_1.update(cx, |buffer_1, cx| buffer_1.redo(cx));
2673            assert_eq!(multibuffer.read(cx).text(), "ABC1234\nAB5678");
2674
2675            multibuffer.undo(cx);
2676            assert_eq!(multibuffer.read(cx).text(), "C1234\n5678");
2677        });
2678    }
2679}