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