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        self.insert_excerpt_after(&ExcerptId::max(), props, cx)
 596    }
 597
 598    pub fn insert_excerpt_after<O>(
 599        &mut self,
 600        prev_excerpt_id: &ExcerptId,
 601        props: ExcerptProperties<O>,
 602        cx: &mut ModelContext<Self>,
 603    ) -> ExcerptId
 604    where
 605        O: text::ToOffset,
 606    {
 607        assert_eq!(self.history.transaction_depth, 0);
 608        self.sync(cx);
 609
 610        let buffer_snapshot = props.buffer.read(cx).snapshot();
 611        let range = buffer_snapshot.anchor_before(&props.range.start)
 612            ..buffer_snapshot.anchor_after(&props.range.end);
 613        let mut snapshot = self.snapshot.borrow_mut();
 614        let mut cursor = snapshot.excerpts.cursor::<Option<&ExcerptId>>();
 615        let mut new_excerpts = cursor.slice(&Some(prev_excerpt_id), Bias::Right, &());
 616
 617        let mut prev_id = ExcerptId::min();
 618        let edit_start = new_excerpts.summary().text.bytes;
 619        new_excerpts.update_last(
 620            |excerpt| {
 621                excerpt.has_trailing_newline = true;
 622                prev_id = excerpt.id.clone();
 623            },
 624            &(),
 625        );
 626
 627        let mut next_id = ExcerptId::max();
 628        if let Some(next_excerpt) = cursor.item() {
 629            next_id = next_excerpt.id.clone();
 630        }
 631
 632        let id = ExcerptId::between(&prev_id, &next_id);
 633
 634        let mut buffers = self.buffers.borrow_mut();
 635        let buffer_state = buffers
 636            .entry(props.buffer.id())
 637            .or_insert_with(|| BufferState {
 638                last_version: buffer_snapshot.version().clone(),
 639                last_parse_count: buffer_snapshot.parse_count(),
 640                last_diagnostics_update_count: buffer_snapshot.diagnostics_update_count(),
 641                excerpts: Default::default(),
 642                _subscriptions: [
 643                    cx.observe(&props.buffer, |_, _, cx| cx.notify()),
 644                    cx.subscribe(&props.buffer, Self::on_buffer_event),
 645                ],
 646                buffer: props.buffer.clone(),
 647            });
 648        if let Err(ix) = buffer_state.excerpts.binary_search(&id) {
 649            buffer_state.excerpts.insert(ix, id.clone());
 650        }
 651
 652        let excerpt = Excerpt::new(
 653            id.clone(),
 654            props.buffer.id(),
 655            buffer_snapshot,
 656            range,
 657            cursor.item().is_some(),
 658        );
 659        new_excerpts.push(excerpt, &());
 660        let edit_end = new_excerpts.summary().text.bytes;
 661
 662        new_excerpts.push_tree(cursor.suffix(&()), &());
 663        drop(cursor);
 664        snapshot.excerpts = new_excerpts;
 665
 666        self.subscriptions.publish_mut([Edit {
 667            old: edit_start..edit_start,
 668            new: edit_start..edit_end,
 669        }]);
 670
 671        cx.notify();
 672        id
 673    }
 674
 675    pub fn excerpt_ids_for_buffer(&self, buffer: &ModelHandle<Buffer>) -> Vec<ExcerptId> {
 676        self.buffers
 677            .borrow()
 678            .get(&buffer.id())
 679            .map_or(Vec::new(), |state| state.excerpts.clone())
 680    }
 681
 682    pub fn remove_excerpts<'a>(
 683        &mut self,
 684        excerpt_ids: impl IntoIterator<Item = &'a ExcerptId>,
 685        cx: &mut ModelContext<Self>,
 686    ) {
 687        let mut buffers = self.buffers.borrow_mut();
 688        let mut snapshot = self.snapshot.borrow_mut();
 689        let mut new_excerpts = SumTree::new();
 690        let mut cursor = snapshot.excerpts.cursor::<(Option<&ExcerptId>, usize)>();
 691        let mut edits = Vec::new();
 692        let mut excerpt_ids = excerpt_ids.into_iter().peekable();
 693
 694        while let Some(mut excerpt_id) = excerpt_ids.next() {
 695            // Seek to the next excerpt to remove, preserving any preceding excerpts.
 696            new_excerpts.push_tree(cursor.slice(&Some(excerpt_id), Bias::Left, &()), &());
 697            if let Some(mut excerpt) = cursor.item() {
 698                if excerpt.id != *excerpt_id {
 699                    continue;
 700                }
 701                let mut old_start = cursor.start().1;
 702
 703                // Skip over the removed excerpt.
 704                loop {
 705                    if let Some(buffer_state) = buffers.get_mut(&excerpt.buffer_id) {
 706                        buffer_state.excerpts.retain(|id| id != excerpt_id);
 707                        if buffer_state.excerpts.is_empty() {
 708                            buffers.remove(&excerpt.buffer_id);
 709                        }
 710                    }
 711                    cursor.next(&());
 712
 713                    // Skip over any subsequent excerpts that are also removed.
 714                    if let Some(&next_excerpt_id) = excerpt_ids.peek() {
 715                        if let Some(next_excerpt) = cursor.item() {
 716                            if next_excerpt.id == *next_excerpt_id {
 717                                excerpt = next_excerpt;
 718                                excerpt_id = excerpt_ids.next().unwrap();
 719                                continue;
 720                            }
 721                        }
 722                    }
 723
 724                    break;
 725                }
 726
 727                // When removing the last excerpt, remove the trailing newline from
 728                // the previous excerpt.
 729                if cursor.item().is_none() && old_start > 0 {
 730                    old_start -= 1;
 731                    new_excerpts.update_last(|e| e.has_trailing_newline = false, &());
 732                }
 733
 734                // Push an edit for the removal of this run of excerpts.
 735                let old_end = cursor.start().1;
 736                let new_start = new_excerpts.summary().text.bytes;
 737                edits.push(Edit {
 738                    old: old_start..old_end,
 739                    new: new_start..new_start,
 740                });
 741            }
 742        }
 743        new_excerpts.push_tree(cursor.suffix(&()), &());
 744        drop(cursor);
 745        snapshot.excerpts = new_excerpts;
 746        self.subscriptions.publish_mut(edits);
 747        cx.notify();
 748    }
 749
 750    fn on_buffer_event(
 751        &mut self,
 752        _: ModelHandle<Buffer>,
 753        event: &Event,
 754        cx: &mut ModelContext<Self>,
 755    ) {
 756        cx.emit(event.clone());
 757    }
 758
 759    pub fn save(&mut self, cx: &mut ModelContext<Self>) -> Result<Task<Result<()>>> {
 760        let mut save_tasks = Vec::new();
 761        for BufferState { buffer, .. } in self.buffers.borrow().values() {
 762            save_tasks.push(buffer.update(cx, |buffer, cx| buffer.save(cx))?);
 763        }
 764
 765        Ok(cx.spawn(|_, _| async move {
 766            for save in save_tasks {
 767                save.await?;
 768            }
 769            Ok(())
 770        }))
 771    }
 772
 773    pub fn language<'a>(&self, cx: &'a AppContext) -> Option<&'a Arc<Language>> {
 774        self.buffers
 775            .borrow()
 776            .values()
 777            .next()
 778            .and_then(|state| state.buffer.read(cx).language())
 779    }
 780
 781    pub fn file<'a>(&self, cx: &'a AppContext) -> Option<&'a dyn File> {
 782        self.as_singleton()?.read(cx).file()
 783    }
 784
 785    #[cfg(test)]
 786    pub fn is_parsing(&self, cx: &AppContext) -> bool {
 787        self.as_singleton().unwrap().read(cx).is_parsing()
 788    }
 789
 790    fn sync(&self, cx: &AppContext) {
 791        let mut snapshot = self.snapshot.borrow_mut();
 792        let mut excerpts_to_edit = Vec::new();
 793        let mut reparsed = false;
 794        let mut diagnostics_updated = false;
 795        let mut is_dirty = false;
 796        let mut has_conflict = false;
 797        let mut buffers = self.buffers.borrow_mut();
 798        for buffer_state in buffers.values_mut() {
 799            let buffer = buffer_state.buffer.read(cx);
 800            let version = buffer.version();
 801            let parse_count = buffer.parse_count();
 802            let diagnostics_update_count = buffer.diagnostics_update_count();
 803
 804            let buffer_edited = version.gt(&buffer_state.last_version);
 805            let buffer_reparsed = parse_count > buffer_state.last_parse_count;
 806            let buffer_diagnostics_updated =
 807                diagnostics_update_count > buffer_state.last_diagnostics_update_count;
 808            if buffer_edited || buffer_reparsed || buffer_diagnostics_updated {
 809                buffer_state.last_version = version;
 810                buffer_state.last_parse_count = parse_count;
 811                buffer_state.last_diagnostics_update_count = diagnostics_update_count;
 812                excerpts_to_edit.extend(
 813                    buffer_state
 814                        .excerpts
 815                        .iter()
 816                        .map(|excerpt_id| (excerpt_id, buffer_state.buffer.clone(), buffer_edited)),
 817                );
 818            }
 819
 820            reparsed |= buffer_reparsed;
 821            diagnostics_updated |= buffer_diagnostics_updated;
 822            is_dirty |= buffer.is_dirty();
 823            has_conflict |= buffer.has_conflict();
 824        }
 825        if reparsed {
 826            snapshot.parse_count += 1;
 827        }
 828        if diagnostics_updated {
 829            snapshot.diagnostics_update_count += 1;
 830        }
 831        snapshot.is_dirty = is_dirty;
 832        snapshot.has_conflict = has_conflict;
 833
 834        excerpts_to_edit.sort_unstable_by_key(|(excerpt_id, _, _)| *excerpt_id);
 835
 836        let mut edits = Vec::new();
 837        let mut new_excerpts = SumTree::new();
 838        let mut cursor = snapshot.excerpts.cursor::<(Option<&ExcerptId>, usize)>();
 839
 840        for (id, buffer, buffer_edited) in excerpts_to_edit {
 841            new_excerpts.push_tree(cursor.slice(&Some(id), Bias::Left, &()), &());
 842            let old_excerpt = cursor.item().unwrap();
 843            let buffer_id = buffer.id();
 844            let buffer = buffer.read(cx);
 845
 846            let mut new_excerpt;
 847            if buffer_edited {
 848                edits.extend(
 849                    buffer
 850                        .edits_since_in_range::<usize>(
 851                            old_excerpt.buffer.version(),
 852                            old_excerpt.range.clone(),
 853                        )
 854                        .map(|mut edit| {
 855                            let excerpt_old_start = cursor.start().1;
 856                            let excerpt_new_start = new_excerpts.summary().text.bytes;
 857                            edit.old.start += excerpt_old_start;
 858                            edit.old.end += excerpt_old_start;
 859                            edit.new.start += excerpt_new_start;
 860                            edit.new.end += excerpt_new_start;
 861                            edit
 862                        }),
 863                );
 864
 865                new_excerpt = Excerpt::new(
 866                    id.clone(),
 867                    buffer_id,
 868                    buffer.snapshot(),
 869                    old_excerpt.range.clone(),
 870                    old_excerpt.has_trailing_newline,
 871                );
 872            } else {
 873                new_excerpt = old_excerpt.clone();
 874                new_excerpt.buffer = buffer.snapshot();
 875            }
 876
 877            new_excerpts.push(new_excerpt, &());
 878            cursor.next(&());
 879        }
 880        new_excerpts.push_tree(cursor.suffix(&()), &());
 881
 882        drop(cursor);
 883        snapshot.excerpts = new_excerpts;
 884
 885        self.subscriptions.publish(edits);
 886    }
 887}
 888
 889#[cfg(any(test, feature = "test-support"))]
 890impl MultiBuffer {
 891    pub fn randomly_edit(
 892        &mut self,
 893        rng: &mut impl rand::Rng,
 894        count: usize,
 895        cx: &mut ModelContext<Self>,
 896    ) {
 897        use text::RandomCharIter;
 898
 899        let snapshot = self.read(cx);
 900        let mut old_ranges: Vec<Range<usize>> = Vec::new();
 901        for _ in 0..count {
 902            let last_end = old_ranges.last().map_or(0, |last_range| last_range.end + 1);
 903            if last_end > snapshot.len() {
 904                break;
 905            }
 906            let end_ix = snapshot.clip_offset(rng.gen_range(0..=last_end), Bias::Right);
 907            let start_ix = snapshot.clip_offset(rng.gen_range(0..=end_ix), Bias::Left);
 908            old_ranges.push(start_ix..end_ix);
 909        }
 910        let new_text_len = rng.gen_range(0..10);
 911        let new_text: String = RandomCharIter::new(&mut *rng).take(new_text_len).collect();
 912        log::info!("mutating multi-buffer at {:?}: {:?}", old_ranges, new_text);
 913        drop(snapshot);
 914
 915        self.edit(old_ranges.iter().cloned(), new_text.as_str(), cx);
 916    }
 917}
 918
 919impl Entity for MultiBuffer {
 920    type Event = language::Event;
 921}
 922
 923impl MultiBufferSnapshot {
 924    pub fn text(&self) -> String {
 925        self.chunks(0..self.len(), None)
 926            .map(|chunk| chunk.text)
 927            .collect()
 928    }
 929
 930    pub fn reversed_chars_at<'a, T: ToOffset>(
 931        &'a self,
 932        position: T,
 933    ) -> impl Iterator<Item = char> + 'a {
 934        let mut offset = position.to_offset(self);
 935        let mut cursor = self.excerpts.cursor::<usize>();
 936        cursor.seek(&offset, Bias::Left, &());
 937        let mut excerpt_chunks = cursor.item().map(|excerpt| {
 938            let end_before_footer = cursor.start() + excerpt.text_summary.bytes;
 939            let start = excerpt.range.start.to_offset(&excerpt.buffer);
 940            let end = start + (cmp::min(offset, end_before_footer) - cursor.start());
 941            excerpt.buffer.reversed_chunks_in_range(start..end)
 942        });
 943        iter::from_fn(move || {
 944            if offset == *cursor.start() {
 945                cursor.prev(&());
 946                let excerpt = cursor.item()?;
 947                excerpt_chunks = Some(
 948                    excerpt
 949                        .buffer
 950                        .reversed_chunks_in_range(excerpt.range.clone()),
 951                );
 952            }
 953
 954            let excerpt = cursor.item().unwrap();
 955            if offset == cursor.end(&()) && excerpt.has_trailing_newline {
 956                offset -= 1;
 957                Some("\n")
 958            } else {
 959                let chunk = excerpt_chunks.as_mut().unwrap().next().unwrap();
 960                offset -= chunk.len();
 961                Some(chunk)
 962            }
 963        })
 964        .flat_map(|c| c.chars().rev())
 965    }
 966
 967    pub fn chars_at<'a, T: ToOffset>(&'a self, position: T) -> impl Iterator<Item = char> + 'a {
 968        let offset = position.to_offset(self);
 969        self.text_for_range(offset..self.len())
 970            .flat_map(|chunk| chunk.chars())
 971    }
 972
 973    pub fn text_for_range<'a, T: ToOffset>(
 974        &'a self,
 975        range: Range<T>,
 976    ) -> impl Iterator<Item = &'a str> {
 977        self.chunks(range, None).map(|chunk| chunk.text)
 978    }
 979
 980    pub fn is_line_blank(&self, row: u32) -> bool {
 981        self.text_for_range(Point::new(row, 0)..Point::new(row, self.line_len(row)))
 982            .all(|chunk| chunk.matches(|c: char| !c.is_whitespace()).next().is_none())
 983    }
 984
 985    pub fn contains_str_at<T>(&self, position: T, needle: &str) -> bool
 986    where
 987        T: ToOffset,
 988    {
 989        let position = position.to_offset(self);
 990        position == self.clip_offset(position, Bias::Left)
 991            && self
 992                .bytes_in_range(position..self.len())
 993                .flatten()
 994                .copied()
 995                .take(needle.len())
 996                .eq(needle.bytes())
 997    }
 998
 999    fn as_singleton(&self) -> Option<&BufferSnapshot> {
1000        let mut excerpts = self.excerpts.iter();
1001        let buffer = excerpts.next().map(|excerpt| &excerpt.buffer);
1002        if excerpts.next().is_none() {
1003            buffer
1004        } else {
1005            None
1006        }
1007    }
1008
1009    pub fn len(&self) -> usize {
1010        self.excerpts.summary().text.bytes
1011    }
1012
1013    pub fn max_buffer_row(&self) -> u32 {
1014        self.excerpts.summary().max_buffer_row
1015    }
1016
1017    pub fn clip_offset(&self, offset: usize, bias: Bias) -> usize {
1018        let mut cursor = self.excerpts.cursor::<usize>();
1019        cursor.seek(&offset, Bias::Right, &());
1020        let overshoot = if let Some(excerpt) = cursor.item() {
1021            let excerpt_start = excerpt.range.start.to_offset(&excerpt.buffer);
1022            let buffer_offset = excerpt
1023                .buffer
1024                .clip_offset(excerpt_start + (offset - cursor.start()), bias);
1025            buffer_offset.saturating_sub(excerpt_start)
1026        } else {
1027            0
1028        };
1029        cursor.start() + overshoot
1030    }
1031
1032    pub fn clip_point(&self, point: Point, bias: Bias) -> Point {
1033        let mut cursor = self.excerpts.cursor::<Point>();
1034        cursor.seek(&point, Bias::Right, &());
1035        let overshoot = if let Some(excerpt) = cursor.item() {
1036            let excerpt_start = excerpt.range.start.to_point(&excerpt.buffer);
1037            let buffer_point = excerpt
1038                .buffer
1039                .clip_point(excerpt_start + (point - cursor.start()), bias);
1040            buffer_point.saturating_sub(excerpt_start)
1041        } else {
1042            Point::zero()
1043        };
1044        *cursor.start() + overshoot
1045    }
1046
1047    pub fn clip_point_utf16(&self, point: PointUtf16, bias: Bias) -> PointUtf16 {
1048        let mut cursor = self.excerpts.cursor::<PointUtf16>();
1049        cursor.seek(&point, Bias::Right, &());
1050        let overshoot = if let Some(excerpt) = cursor.item() {
1051            let excerpt_start = excerpt
1052                .buffer
1053                .offset_to_point_utf16(excerpt.range.start.to_offset(&excerpt.buffer));
1054            let buffer_point = excerpt
1055                .buffer
1056                .clip_point_utf16(excerpt_start + (point - cursor.start()), bias);
1057            buffer_point.saturating_sub(excerpt_start)
1058        } else {
1059            PointUtf16::zero()
1060        };
1061        *cursor.start() + overshoot
1062    }
1063
1064    pub fn bytes_in_range<'a, T: ToOffset>(&'a self, range: Range<T>) -> MultiBufferBytes<'a> {
1065        let range = range.start.to_offset(self)..range.end.to_offset(self);
1066        let mut excerpts = self.excerpts.cursor::<usize>();
1067        excerpts.seek(&range.start, Bias::Right, &());
1068
1069        let mut chunk = &[][..];
1070        let excerpt_bytes = if let Some(excerpt) = excerpts.item() {
1071            let mut excerpt_bytes = excerpt
1072                .bytes_in_range(range.start - excerpts.start()..range.end - excerpts.start());
1073            chunk = excerpt_bytes.next().unwrap_or(&[][..]);
1074            Some(excerpt_bytes)
1075        } else {
1076            None
1077        };
1078
1079        MultiBufferBytes {
1080            range,
1081            excerpts,
1082            excerpt_bytes,
1083            chunk,
1084        }
1085    }
1086
1087    pub fn buffer_rows<'a>(&'a self, start_row: u32) -> MultiBufferRows<'a> {
1088        let mut result = MultiBufferRows {
1089            buffer_row_range: 0..0,
1090            excerpts: self.excerpts.cursor(),
1091        };
1092        result.seek(start_row);
1093        result
1094    }
1095
1096    pub fn chunks<'a, T: ToOffset>(
1097        &'a self,
1098        range: Range<T>,
1099        theme: Option<&'a SyntaxTheme>,
1100    ) -> MultiBufferChunks<'a> {
1101        let range = range.start.to_offset(self)..range.end.to_offset(self);
1102        let mut chunks = MultiBufferChunks {
1103            range: range.clone(),
1104            excerpts: self.excerpts.cursor(),
1105            excerpt_chunks: None,
1106            theme,
1107        };
1108        chunks.seek(range.start);
1109        chunks
1110    }
1111
1112    pub fn offset_to_point(&self, offset: usize) -> Point {
1113        let mut cursor = self.excerpts.cursor::<(usize, Point)>();
1114        cursor.seek(&offset, Bias::Right, &());
1115        if let Some(excerpt) = cursor.item() {
1116            let (start_offset, start_point) = cursor.start();
1117            let overshoot = offset - start_offset;
1118            let excerpt_start_offset = excerpt.range.start.to_offset(&excerpt.buffer);
1119            let excerpt_start_point = excerpt.range.start.to_point(&excerpt.buffer);
1120            let buffer_point = excerpt
1121                .buffer
1122                .offset_to_point(excerpt_start_offset + overshoot);
1123            *start_point + (buffer_point - excerpt_start_point)
1124        } else {
1125            self.excerpts.summary().text.lines
1126        }
1127    }
1128
1129    pub fn point_to_offset(&self, point: Point) -> usize {
1130        let mut cursor = self.excerpts.cursor::<(Point, usize)>();
1131        cursor.seek(&point, Bias::Right, &());
1132        if let Some(excerpt) = cursor.item() {
1133            let (start_point, start_offset) = cursor.start();
1134            let overshoot = point - start_point;
1135            let excerpt_start_offset = excerpt.range.start.to_offset(&excerpt.buffer);
1136            let excerpt_start_point = excerpt.range.start.to_point(&excerpt.buffer);
1137            let buffer_offset = excerpt
1138                .buffer
1139                .point_to_offset(excerpt_start_point + overshoot);
1140            *start_offset + buffer_offset - excerpt_start_offset
1141        } else {
1142            self.excerpts.summary().text.bytes
1143        }
1144    }
1145
1146    pub fn point_utf16_to_offset(&self, point: PointUtf16) -> usize {
1147        let mut cursor = self.excerpts.cursor::<(PointUtf16, usize)>();
1148        cursor.seek(&point, Bias::Right, &());
1149        if let Some(excerpt) = cursor.item() {
1150            let (start_point, start_offset) = cursor.start();
1151            let overshoot = point - start_point;
1152            let excerpt_start_offset = excerpt.range.start.to_offset(&excerpt.buffer);
1153            let excerpt_start_point = excerpt
1154                .buffer
1155                .offset_to_point_utf16(excerpt.range.start.to_offset(&excerpt.buffer));
1156            let buffer_offset = excerpt
1157                .buffer
1158                .point_utf16_to_offset(excerpt_start_point + overshoot);
1159            *start_offset + (buffer_offset - excerpt_start_offset)
1160        } else {
1161            self.excerpts.summary().text.bytes
1162        }
1163    }
1164
1165    pub fn indent_column_for_line(&self, row: u32) -> u32 {
1166        if let Some((buffer, range)) = self.buffer_line_for_row(row) {
1167            buffer
1168                .indent_column_for_line(range.start.row)
1169                .min(range.end.column)
1170                .saturating_sub(range.start.column)
1171        } else {
1172            0
1173        }
1174    }
1175
1176    pub fn line_len(&self, row: u32) -> u32 {
1177        if let Some((_, range)) = self.buffer_line_for_row(row) {
1178            range.end.column - range.start.column
1179        } else {
1180            0
1181        }
1182    }
1183
1184    fn buffer_line_for_row(&self, row: u32) -> Option<(&BufferSnapshot, Range<Point>)> {
1185        let mut cursor = self.excerpts.cursor::<Point>();
1186        cursor.seek(&Point::new(row, 0), Bias::Right, &());
1187        if let Some(excerpt) = cursor.item() {
1188            let overshoot = row - cursor.start().row;
1189            let excerpt_start = excerpt.range.start.to_point(&excerpt.buffer);
1190            let excerpt_end = excerpt.range.end.to_point(&excerpt.buffer);
1191            let buffer_row = excerpt_start.row + overshoot;
1192            let line_start = Point::new(buffer_row, 0);
1193            let line_end = Point::new(buffer_row, excerpt.buffer.line_len(buffer_row));
1194            return Some((
1195                &excerpt.buffer,
1196                line_start.max(excerpt_start)..line_end.min(excerpt_end),
1197            ));
1198        }
1199        None
1200    }
1201
1202    pub fn max_point(&self) -> Point {
1203        self.text_summary().lines
1204    }
1205
1206    pub fn text_summary(&self) -> TextSummary {
1207        self.excerpts.summary().text
1208    }
1209
1210    pub fn text_summary_for_range<'a, D, O>(&'a self, range: Range<O>) -> D
1211    where
1212        D: TextDimension,
1213        O: ToOffset,
1214    {
1215        let mut summary = D::default();
1216        let mut range = range.start.to_offset(self)..range.end.to_offset(self);
1217        let mut cursor = self.excerpts.cursor::<usize>();
1218        cursor.seek(&range.start, Bias::Right, &());
1219        if let Some(excerpt) = cursor.item() {
1220            let mut end_before_newline = cursor.end(&());
1221            if excerpt.has_trailing_newline {
1222                end_before_newline -= 1;
1223            }
1224
1225            let excerpt_start = excerpt.range.start.to_offset(&excerpt.buffer);
1226            let start_in_excerpt = excerpt_start + (range.start - cursor.start());
1227            let end_in_excerpt =
1228                excerpt_start + (cmp::min(end_before_newline, range.end) - cursor.start());
1229            summary.add_assign(
1230                &excerpt
1231                    .buffer
1232                    .text_summary_for_range(start_in_excerpt..end_in_excerpt),
1233            );
1234
1235            if range.end > end_before_newline {
1236                summary.add_assign(&D::from_text_summary(&TextSummary {
1237                    bytes: 1,
1238                    lines: Point::new(1 as u32, 0),
1239                    lines_utf16: PointUtf16::new(1 as u32, 0),
1240                    first_line_chars: 0,
1241                    last_line_chars: 0,
1242                    longest_row: 0,
1243                    longest_row_chars: 0,
1244                }));
1245            }
1246
1247            cursor.next(&());
1248        }
1249
1250        if range.end > *cursor.start() {
1251            summary.add_assign(&D::from_text_summary(&cursor.summary::<_, TextSummary>(
1252                &range.end,
1253                Bias::Right,
1254                &(),
1255            )));
1256            if let Some(excerpt) = cursor.item() {
1257                range.end = cmp::max(*cursor.start(), range.end);
1258
1259                let excerpt_start = excerpt.range.start.to_offset(&excerpt.buffer);
1260                let end_in_excerpt = excerpt_start + (range.end - cursor.start());
1261                summary.add_assign(
1262                    &excerpt
1263                        .buffer
1264                        .text_summary_for_range(excerpt_start..end_in_excerpt),
1265                );
1266            }
1267        }
1268
1269        summary
1270    }
1271
1272    pub fn summary_for_anchor<D>(&self, anchor: &Anchor) -> D
1273    where
1274        D: TextDimension + Ord + Sub<D, Output = D>,
1275    {
1276        let mut cursor = self.excerpts.cursor::<ExcerptSummary>();
1277        cursor.seek(&Some(&anchor.excerpt_id), Bias::Left, &());
1278        if cursor.item().is_none() {
1279            cursor.next(&());
1280        }
1281
1282        let mut position = D::from_text_summary(&cursor.start().text);
1283        if let Some(excerpt) = cursor.item() {
1284            if excerpt.id == anchor.excerpt_id {
1285                let excerpt_buffer_start = excerpt.range.start.summary::<D>(&excerpt.buffer);
1286                let buffer_position = anchor.text_anchor.summary::<D>(&excerpt.buffer);
1287                if buffer_position > excerpt_buffer_start {
1288                    position.add_assign(&(buffer_position - excerpt_buffer_start));
1289                }
1290            }
1291        }
1292        position
1293    }
1294
1295    pub fn summaries_for_anchors<'a, D, I>(&'a self, anchors: I) -> Vec<D>
1296    where
1297        D: TextDimension + Ord + Sub<D, Output = D>,
1298        I: 'a + IntoIterator<Item = &'a Anchor>,
1299    {
1300        let mut anchors = anchors.into_iter().peekable();
1301        let mut cursor = self.excerpts.cursor::<ExcerptSummary>();
1302        let mut summaries = Vec::new();
1303        while let Some(anchor) = anchors.peek() {
1304            let excerpt_id = &anchor.excerpt_id;
1305            let excerpt_anchors = iter::from_fn(|| {
1306                let anchor = anchors.peek()?;
1307                if anchor.excerpt_id == *excerpt_id {
1308                    Some(&anchors.next().unwrap().text_anchor)
1309                } else {
1310                    None
1311                }
1312            });
1313
1314            cursor.seek_forward(&Some(excerpt_id), Bias::Left, &());
1315            if cursor.item().is_none() {
1316                cursor.next(&());
1317            }
1318
1319            let position = D::from_text_summary(&cursor.start().text);
1320            if let Some(excerpt) = cursor.item() {
1321                if excerpt.id == *excerpt_id {
1322                    let excerpt_buffer_start = excerpt.range.start.summary::<D>(&excerpt.buffer);
1323                    summaries.extend(
1324                        excerpt
1325                            .buffer
1326                            .summaries_for_anchors::<D, _>(excerpt_anchors)
1327                            .map(move |summary| {
1328                                let mut position = position.clone();
1329                                let excerpt_buffer_start = excerpt_buffer_start.clone();
1330                                if summary > excerpt_buffer_start {
1331                                    position.add_assign(&(summary - excerpt_buffer_start));
1332                                }
1333                                position
1334                            }),
1335                    );
1336                    continue;
1337                }
1338            }
1339
1340            summaries.extend(excerpt_anchors.map(|_| position.clone()));
1341        }
1342
1343        summaries
1344    }
1345
1346    pub fn anchor_before<T: ToOffset>(&self, position: T) -> Anchor {
1347        self.anchor_at(position, Bias::Left)
1348    }
1349
1350    pub fn anchor_after<T: ToOffset>(&self, position: T) -> Anchor {
1351        self.anchor_at(position, Bias::Right)
1352    }
1353
1354    pub fn anchor_at<T: ToOffset>(&self, position: T, mut bias: Bias) -> Anchor {
1355        let offset = position.to_offset(self);
1356        let mut cursor = self.excerpts.cursor::<(usize, Option<&ExcerptId>)>();
1357        cursor.seek(&offset, Bias::Right, &());
1358        if cursor.item().is_none() && offset == cursor.start().0 && bias == Bias::Left {
1359            cursor.prev(&());
1360        }
1361        if let Some(excerpt) = cursor.item() {
1362            let mut overshoot = offset.saturating_sub(cursor.start().0);
1363            if excerpt.has_trailing_newline && offset == cursor.end(&()).0 {
1364                overshoot -= 1;
1365                bias = Bias::Right;
1366            }
1367
1368            let buffer_start = excerpt.range.start.to_offset(&excerpt.buffer);
1369            let text_anchor =
1370                excerpt.clip_anchor(excerpt.buffer.anchor_at(buffer_start + overshoot, bias));
1371            Anchor {
1372                excerpt_id: excerpt.id.clone(),
1373                text_anchor,
1374            }
1375        } else if offset == 0 && bias == Bias::Left {
1376            Anchor::min()
1377        } else {
1378            Anchor::max()
1379        }
1380    }
1381
1382    pub fn anchor_in_excerpt(&self, excerpt_id: ExcerptId, text_anchor: text::Anchor) -> Anchor {
1383        let mut cursor = self.excerpts.cursor::<Option<&ExcerptId>>();
1384        cursor.seek(&Some(&excerpt_id), Bias::Left, &());
1385        if let Some(excerpt) = cursor.item() {
1386            if excerpt.id == excerpt_id {
1387                let text_anchor = excerpt.clip_anchor(text_anchor);
1388                drop(cursor);
1389                return Anchor {
1390                    excerpt_id,
1391                    text_anchor,
1392                };
1393            }
1394        }
1395        panic!("excerpt not found");
1396    }
1397
1398    pub fn range_contains_excerpt_boundary<T: ToOffset>(&self, range: Range<T>) -> bool {
1399        let start = range.start.to_offset(self);
1400        let end = range.end.to_offset(self);
1401        let mut cursor = self.excerpts.cursor::<(usize, Option<&ExcerptId>)>();
1402        cursor.seek(&start, Bias::Right, &());
1403        let start_id = cursor
1404            .item()
1405            .or_else(|| cursor.prev_item())
1406            .map(|excerpt| &excerpt.id);
1407        cursor.seek_forward(&end, Bias::Right, &());
1408        let end_id = cursor
1409            .item()
1410            .or_else(|| cursor.prev_item())
1411            .map(|excerpt| &excerpt.id);
1412        start_id != end_id
1413    }
1414
1415    pub fn parse_count(&self) -> usize {
1416        self.parse_count
1417    }
1418
1419    pub fn enclosing_bracket_ranges<T: ToOffset>(
1420        &self,
1421        range: Range<T>,
1422    ) -> Option<(Range<usize>, Range<usize>)> {
1423        let range = range.start.to_offset(self)..range.end.to_offset(self);
1424
1425        let mut cursor = self.excerpts.cursor::<usize>();
1426        cursor.seek(&range.start, Bias::Right, &());
1427        let start_excerpt = cursor.item();
1428
1429        cursor.seek(&range.end, Bias::Right, &());
1430        let end_excerpt = cursor.item();
1431
1432        start_excerpt
1433            .zip(end_excerpt)
1434            .and_then(|(start_excerpt, end_excerpt)| {
1435                if start_excerpt.id != end_excerpt.id {
1436                    return None;
1437                }
1438
1439                let excerpt_buffer_start =
1440                    start_excerpt.range.start.to_offset(&start_excerpt.buffer);
1441                let excerpt_buffer_end = excerpt_buffer_start + start_excerpt.text_summary.bytes;
1442
1443                let start_in_buffer =
1444                    excerpt_buffer_start + range.start.saturating_sub(*cursor.start());
1445                let end_in_buffer =
1446                    excerpt_buffer_start + range.end.saturating_sub(*cursor.start());
1447                let (mut start_bracket_range, mut end_bracket_range) = start_excerpt
1448                    .buffer
1449                    .enclosing_bracket_ranges(start_in_buffer..end_in_buffer)?;
1450
1451                if start_bracket_range.start >= excerpt_buffer_start
1452                    && end_bracket_range.end < excerpt_buffer_end
1453                {
1454                    start_bracket_range.start =
1455                        cursor.start() + (start_bracket_range.start - excerpt_buffer_start);
1456                    start_bracket_range.end =
1457                        cursor.start() + (start_bracket_range.end - excerpt_buffer_start);
1458                    end_bracket_range.start =
1459                        cursor.start() + (end_bracket_range.start - excerpt_buffer_start);
1460                    end_bracket_range.end =
1461                        cursor.start() + (end_bracket_range.end - excerpt_buffer_start);
1462                    Some((start_bracket_range, end_bracket_range))
1463                } else {
1464                    None
1465                }
1466            })
1467    }
1468
1469    pub fn diagnostics_update_count(&self) -> usize {
1470        self.diagnostics_update_count
1471    }
1472
1473    pub fn language(&self) -> Option<&Arc<Language>> {
1474        self.excerpts
1475            .iter()
1476            .next()
1477            .and_then(|excerpt| excerpt.buffer.language())
1478    }
1479
1480    pub fn is_dirty(&self) -> bool {
1481        self.is_dirty
1482    }
1483
1484    pub fn has_conflict(&self) -> bool {
1485        self.has_conflict
1486    }
1487
1488    pub fn diagnostic_group<'a, O>(
1489        &'a self,
1490        provider_name: &'a str,
1491        group_id: usize,
1492    ) -> impl Iterator<Item = DiagnosticEntry<O>> + 'a
1493    where
1494        O: text::FromAnchor + 'a,
1495    {
1496        self.as_singleton()
1497            .into_iter()
1498            .flat_map(move |buffer| buffer.diagnostic_group(provider_name, group_id))
1499    }
1500
1501    pub fn diagnostics_in_range<'a, T, O>(
1502        &'a self,
1503        range: Range<T>,
1504    ) -> impl Iterator<Item = (&'a str, DiagnosticEntry<O>)> + 'a
1505    where
1506        T: 'a + ToOffset,
1507        O: 'a + text::FromAnchor,
1508    {
1509        self.as_singleton().into_iter().flat_map(move |buffer| {
1510            buffer.diagnostics_in_range(range.start.to_offset(self)..range.end.to_offset(self))
1511        })
1512    }
1513
1514    pub fn range_for_syntax_ancestor<T: ToOffset>(&self, range: Range<T>) -> Option<Range<usize>> {
1515        let range = range.start.to_offset(self)..range.end.to_offset(self);
1516
1517        let mut cursor = self.excerpts.cursor::<usize>();
1518        cursor.seek(&range.start, Bias::Right, &());
1519        let start_excerpt = cursor.item();
1520
1521        cursor.seek(&range.end, Bias::Right, &());
1522        let end_excerpt = cursor.item();
1523
1524        start_excerpt
1525            .zip(end_excerpt)
1526            .and_then(|(start_excerpt, end_excerpt)| {
1527                if start_excerpt.id != end_excerpt.id {
1528                    return None;
1529                }
1530
1531                let excerpt_buffer_start =
1532                    start_excerpt.range.start.to_offset(&start_excerpt.buffer);
1533                let excerpt_buffer_end = excerpt_buffer_start + start_excerpt.text_summary.bytes;
1534
1535                let start_in_buffer =
1536                    excerpt_buffer_start + range.start.saturating_sub(*cursor.start());
1537                let end_in_buffer =
1538                    excerpt_buffer_start + range.end.saturating_sub(*cursor.start());
1539                let mut ancestor_buffer_range = start_excerpt
1540                    .buffer
1541                    .range_for_syntax_ancestor(start_in_buffer..end_in_buffer)?;
1542                ancestor_buffer_range.start =
1543                    cmp::max(ancestor_buffer_range.start, excerpt_buffer_start);
1544                ancestor_buffer_range.end = cmp::min(ancestor_buffer_range.end, excerpt_buffer_end);
1545
1546                let start = cursor.start() + (ancestor_buffer_range.start - excerpt_buffer_start);
1547                let end = cursor.start() + (ancestor_buffer_range.end - excerpt_buffer_start);
1548                Some(start..end)
1549            })
1550    }
1551
1552    fn buffer_snapshot_for_excerpt<'a>(
1553        &'a self,
1554        excerpt_id: &'a ExcerptId,
1555    ) -> Option<&'a BufferSnapshot> {
1556        let mut cursor = self.excerpts.cursor::<Option<&ExcerptId>>();
1557        cursor.seek(&Some(excerpt_id), Bias::Left, &());
1558        if let Some(excerpt) = cursor.item() {
1559            if excerpt.id == *excerpt_id {
1560                return Some(&excerpt.buffer);
1561            }
1562        }
1563        None
1564    }
1565
1566    pub fn remote_selections_in_range<'a>(
1567        &'a self,
1568        range: &'a Range<Anchor>,
1569    ) -> impl 'a + Iterator<Item = (ReplicaId, Selection<Anchor>)> {
1570        let mut cursor = self.excerpts.cursor::<Option<&ExcerptId>>();
1571        cursor.seek(&Some(&range.start.excerpt_id), Bias::Left, &());
1572        cursor
1573            .take_while(move |excerpt| excerpt.id <= range.end.excerpt_id)
1574            .flat_map(move |excerpt| {
1575                let mut query_range = excerpt.range.start.clone()..excerpt.range.end.clone();
1576                if excerpt.id == range.start.excerpt_id {
1577                    query_range.start = range.start.text_anchor.clone();
1578                }
1579                if excerpt.id == range.end.excerpt_id {
1580                    query_range.end = range.end.text_anchor.clone();
1581                }
1582
1583                excerpt
1584                    .buffer
1585                    .remote_selections_in_range(query_range)
1586                    .flat_map(move |(replica_id, selections)| {
1587                        selections.map(move |selection| {
1588                            let mut start = Anchor {
1589                                excerpt_id: excerpt.id.clone(),
1590                                text_anchor: selection.start.clone(),
1591                            };
1592                            let mut end = Anchor {
1593                                excerpt_id: excerpt.id.clone(),
1594                                text_anchor: selection.end.clone(),
1595                            };
1596                            if range.start.cmp(&start, self).unwrap().is_gt() {
1597                                start = range.start.clone();
1598                            }
1599                            if range.end.cmp(&end, self).unwrap().is_lt() {
1600                                end = range.end.clone();
1601                            }
1602
1603                            (
1604                                replica_id,
1605                                Selection {
1606                                    id: selection.id,
1607                                    start,
1608                                    end,
1609                                    reversed: selection.reversed,
1610                                    goal: selection.goal,
1611                                },
1612                            )
1613                        })
1614                    })
1615            })
1616    }
1617}
1618
1619impl History {
1620    fn start_transaction(&mut self, now: Instant) -> Option<TransactionId> {
1621        self.transaction_depth += 1;
1622        if self.transaction_depth == 1 {
1623            let id = post_inc(&mut self.next_transaction_id);
1624            self.undo_stack.push(Transaction {
1625                id,
1626                buffer_transactions: Default::default(),
1627                first_edit_at: now,
1628                last_edit_at: now,
1629            });
1630            Some(id)
1631        } else {
1632            None
1633        }
1634    }
1635
1636    fn end_transaction(
1637        &mut self,
1638        now: Instant,
1639        buffer_transactions: HashSet<(usize, TransactionId)>,
1640    ) -> bool {
1641        assert_ne!(self.transaction_depth, 0);
1642        self.transaction_depth -= 1;
1643        if self.transaction_depth == 0 {
1644            if buffer_transactions.is_empty() {
1645                self.undo_stack.pop();
1646                false
1647            } else {
1648                let transaction = self.undo_stack.last_mut().unwrap();
1649                transaction.last_edit_at = now;
1650                transaction.buffer_transactions.extend(buffer_transactions);
1651                true
1652            }
1653        } else {
1654            false
1655        }
1656    }
1657
1658    fn pop_undo(&mut self) -> Option<&Transaction> {
1659        assert_eq!(self.transaction_depth, 0);
1660        if let Some(transaction) = self.undo_stack.pop() {
1661            self.redo_stack.push(transaction);
1662            self.redo_stack.last()
1663        } else {
1664            None
1665        }
1666    }
1667
1668    fn pop_redo(&mut self) -> Option<&Transaction> {
1669        assert_eq!(self.transaction_depth, 0);
1670        if let Some(transaction) = self.redo_stack.pop() {
1671            self.undo_stack.push(transaction);
1672            self.undo_stack.last()
1673        } else {
1674            None
1675        }
1676    }
1677
1678    fn group(&mut self) -> Option<TransactionId> {
1679        let mut new_len = self.undo_stack.len();
1680        let mut transactions = self.undo_stack.iter_mut();
1681
1682        if let Some(mut transaction) = transactions.next_back() {
1683            while let Some(prev_transaction) = transactions.next_back() {
1684                if transaction.first_edit_at - prev_transaction.last_edit_at <= self.group_interval
1685                {
1686                    transaction = prev_transaction;
1687                    new_len -= 1;
1688                } else {
1689                    break;
1690                }
1691            }
1692        }
1693
1694        let (transactions_to_keep, transactions_to_merge) = self.undo_stack.split_at_mut(new_len);
1695        if let Some(last_transaction) = transactions_to_keep.last_mut() {
1696            if let Some(transaction) = transactions_to_merge.last() {
1697                last_transaction.last_edit_at = transaction.last_edit_at;
1698            }
1699        }
1700
1701        self.undo_stack.truncate(new_len);
1702        self.undo_stack.last().map(|t| t.id)
1703    }
1704}
1705
1706impl Excerpt {
1707    fn new(
1708        id: ExcerptId,
1709        buffer_id: usize,
1710        buffer: BufferSnapshot,
1711        range: Range<text::Anchor>,
1712        has_trailing_newline: bool,
1713    ) -> Self {
1714        Excerpt {
1715            id,
1716            max_buffer_row: range.end.to_point(&buffer).row,
1717            text_summary: buffer.text_summary_for_range::<TextSummary, _>(range.to_offset(&buffer)),
1718            buffer_id,
1719            buffer,
1720            range,
1721            has_trailing_newline,
1722        }
1723    }
1724
1725    fn chunks_in_range<'a>(
1726        &'a self,
1727        range: Range<usize>,
1728        theme: Option<&'a SyntaxTheme>,
1729    ) -> ExcerptChunks<'a> {
1730        let content_start = self.range.start.to_offset(&self.buffer);
1731        let chunks_start = content_start + range.start;
1732        let chunks_end = content_start + cmp::min(range.end, self.text_summary.bytes);
1733
1734        let footer_height = if self.has_trailing_newline
1735            && range.start <= self.text_summary.bytes
1736            && range.end > self.text_summary.bytes
1737        {
1738            1
1739        } else {
1740            0
1741        };
1742
1743        let content_chunks = self.buffer.chunks(chunks_start..chunks_end, theme);
1744
1745        ExcerptChunks {
1746            content_chunks,
1747            footer_height,
1748        }
1749    }
1750
1751    fn bytes_in_range(&self, range: Range<usize>) -> ExcerptBytes {
1752        let content_start = self.range.start.to_offset(&self.buffer);
1753        let bytes_start = content_start + range.start;
1754        let bytes_end = content_start + cmp::min(range.end, self.text_summary.bytes);
1755        let footer_height = if self.has_trailing_newline
1756            && range.start <= self.text_summary.bytes
1757            && range.end > self.text_summary.bytes
1758        {
1759            1
1760        } else {
1761            0
1762        };
1763        let content_bytes = self.buffer.bytes_in_range(bytes_start..bytes_end);
1764
1765        ExcerptBytes {
1766            content_bytes,
1767            footer_height,
1768        }
1769    }
1770
1771    fn clip_anchor(&self, text_anchor: text::Anchor) -> text::Anchor {
1772        if text_anchor
1773            .cmp(&self.range.start, &self.buffer)
1774            .unwrap()
1775            .is_lt()
1776        {
1777            self.range.start.clone()
1778        } else if text_anchor
1779            .cmp(&self.range.end, &self.buffer)
1780            .unwrap()
1781            .is_gt()
1782        {
1783            self.range.end.clone()
1784        } else {
1785            text_anchor
1786        }
1787    }
1788}
1789
1790impl fmt::Debug for Excerpt {
1791    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1792        f.debug_struct("Excerpt")
1793            .field("id", &self.id)
1794            .field("buffer_id", &self.buffer_id)
1795            .field("range", &self.range)
1796            .field("text_summary", &self.text_summary)
1797            .field("has_trailing_newline", &self.has_trailing_newline)
1798            .finish()
1799    }
1800}
1801
1802impl sum_tree::Item for Excerpt {
1803    type Summary = ExcerptSummary;
1804
1805    fn summary(&self) -> Self::Summary {
1806        let mut text = self.text_summary.clone();
1807        if self.has_trailing_newline {
1808            text += TextSummary::from("\n");
1809        }
1810        ExcerptSummary {
1811            excerpt_id: self.id.clone(),
1812            max_buffer_row: self.max_buffer_row,
1813            text,
1814        }
1815    }
1816}
1817
1818impl sum_tree::Summary for ExcerptSummary {
1819    type Context = ();
1820
1821    fn add_summary(&mut self, summary: &Self, _: &()) {
1822        debug_assert!(summary.excerpt_id > self.excerpt_id);
1823        self.excerpt_id = summary.excerpt_id.clone();
1824        self.text.add_summary(&summary.text, &());
1825        self.max_buffer_row = cmp::max(self.max_buffer_row, summary.max_buffer_row);
1826    }
1827}
1828
1829impl<'a> sum_tree::Dimension<'a, ExcerptSummary> for TextSummary {
1830    fn add_summary(&mut self, summary: &'a ExcerptSummary, _: &()) {
1831        *self += &summary.text;
1832    }
1833}
1834
1835impl<'a> sum_tree::Dimension<'a, ExcerptSummary> for usize {
1836    fn add_summary(&mut self, summary: &'a ExcerptSummary, _: &()) {
1837        *self += summary.text.bytes;
1838    }
1839}
1840
1841impl<'a> sum_tree::SeekTarget<'a, ExcerptSummary, ExcerptSummary> for usize {
1842    fn cmp(&self, cursor_location: &ExcerptSummary, _: &()) -> cmp::Ordering {
1843        Ord::cmp(self, &cursor_location.text.bytes)
1844    }
1845}
1846
1847impl<'a> sum_tree::SeekTarget<'a, ExcerptSummary, ExcerptSummary> for Option<&'a ExcerptId> {
1848    fn cmp(&self, cursor_location: &ExcerptSummary, _: &()) -> cmp::Ordering {
1849        Ord::cmp(self, &Some(&cursor_location.excerpt_id))
1850    }
1851}
1852
1853impl<'a> sum_tree::Dimension<'a, ExcerptSummary> for Point {
1854    fn add_summary(&mut self, summary: &'a ExcerptSummary, _: &()) {
1855        *self += summary.text.lines;
1856    }
1857}
1858
1859impl<'a> sum_tree::Dimension<'a, ExcerptSummary> for PointUtf16 {
1860    fn add_summary(&mut self, summary: &'a ExcerptSummary, _: &()) {
1861        *self += summary.text.lines_utf16
1862    }
1863}
1864
1865impl<'a> sum_tree::Dimension<'a, ExcerptSummary> for Option<&'a ExcerptId> {
1866    fn add_summary(&mut self, summary: &'a ExcerptSummary, _: &()) {
1867        *self = Some(&summary.excerpt_id);
1868    }
1869}
1870
1871impl<'a> MultiBufferRows<'a> {
1872    pub fn seek(&mut self, row: u32) {
1873        self.buffer_row_range = 0..0;
1874
1875        self.excerpts
1876            .seek_forward(&Point::new(row, 0), Bias::Right, &());
1877        if self.excerpts.item().is_none() {
1878            self.excerpts.prev(&());
1879
1880            if self.excerpts.item().is_none() && row == 0 {
1881                self.buffer_row_range = 0..1;
1882                return;
1883            }
1884        }
1885
1886        if let Some(excerpt) = self.excerpts.item() {
1887            let overshoot = row - self.excerpts.start().row;
1888            let excerpt_start = excerpt.range.start.to_point(&excerpt.buffer).row;
1889            self.buffer_row_range.start = excerpt_start + overshoot;
1890            self.buffer_row_range.end = excerpt_start + excerpt.text_summary.lines.row + 1;
1891        }
1892    }
1893}
1894
1895impl<'a> Iterator for MultiBufferRows<'a> {
1896    type Item = Option<u32>;
1897
1898    fn next(&mut self) -> Option<Self::Item> {
1899        loop {
1900            if !self.buffer_row_range.is_empty() {
1901                let row = Some(self.buffer_row_range.start);
1902                self.buffer_row_range.start += 1;
1903                return Some(row);
1904            }
1905            self.excerpts.item()?;
1906            self.excerpts.next(&());
1907            let excerpt = self.excerpts.item()?;
1908            self.buffer_row_range.start = excerpt.range.start.to_point(&excerpt.buffer).row;
1909            self.buffer_row_range.end =
1910                self.buffer_row_range.start + excerpt.text_summary.lines.row + 1;
1911        }
1912    }
1913}
1914
1915impl<'a> MultiBufferChunks<'a> {
1916    pub fn offset(&self) -> usize {
1917        self.range.start
1918    }
1919
1920    pub fn seek(&mut self, offset: usize) {
1921        self.range.start = offset;
1922        self.excerpts.seek(&offset, Bias::Right, &());
1923        if let Some(excerpt) = self.excerpts.item() {
1924            self.excerpt_chunks = Some(excerpt.chunks_in_range(
1925                self.range.start - self.excerpts.start()..self.range.end - self.excerpts.start(),
1926                self.theme,
1927            ));
1928        } else {
1929            self.excerpt_chunks = None;
1930        }
1931    }
1932}
1933
1934impl<'a> Iterator for MultiBufferChunks<'a> {
1935    type Item = Chunk<'a>;
1936
1937    fn next(&mut self) -> Option<Self::Item> {
1938        if self.range.is_empty() {
1939            None
1940        } else if let Some(chunk) = self.excerpt_chunks.as_mut()?.next() {
1941            self.range.start += chunk.text.len();
1942            Some(chunk)
1943        } else {
1944            self.excerpts.next(&());
1945            let excerpt = self.excerpts.item()?;
1946            self.excerpt_chunks = Some(
1947                excerpt.chunks_in_range(0..self.range.end - self.excerpts.start(), self.theme),
1948            );
1949            self.next()
1950        }
1951    }
1952}
1953
1954impl<'a> MultiBufferBytes<'a> {
1955    fn consume(&mut self, len: usize) {
1956        self.range.start += len;
1957        self.chunk = &self.chunk[len..];
1958
1959        if !self.range.is_empty() && self.chunk.is_empty() {
1960            if let Some(chunk) = self.excerpt_bytes.as_mut().and_then(|bytes| bytes.next()) {
1961                self.chunk = chunk;
1962            } else {
1963                self.excerpts.next(&());
1964                if let Some(excerpt) = self.excerpts.item() {
1965                    let mut excerpt_bytes =
1966                        excerpt.bytes_in_range(0..self.range.end - self.excerpts.start());
1967                    self.chunk = excerpt_bytes.next().unwrap();
1968                    self.excerpt_bytes = Some(excerpt_bytes);
1969                }
1970            }
1971        }
1972    }
1973}
1974
1975impl<'a> Iterator for MultiBufferBytes<'a> {
1976    type Item = &'a [u8];
1977
1978    fn next(&mut self) -> Option<Self::Item> {
1979        let chunk = self.chunk;
1980        if chunk.is_empty() {
1981            None
1982        } else {
1983            self.consume(chunk.len());
1984            Some(chunk)
1985        }
1986    }
1987}
1988
1989impl<'a> io::Read for MultiBufferBytes<'a> {
1990    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
1991        let len = cmp::min(buf.len(), self.chunk.len());
1992        buf[..len].copy_from_slice(&self.chunk[..len]);
1993        if len > 0 {
1994            self.consume(len);
1995        }
1996        Ok(len)
1997    }
1998}
1999
2000impl<'a> Iterator for ExcerptBytes<'a> {
2001    type Item = &'a [u8];
2002
2003    fn next(&mut self) -> Option<Self::Item> {
2004        if let Some(chunk) = self.content_bytes.next() {
2005            if !chunk.is_empty() {
2006                return Some(chunk);
2007            }
2008        }
2009
2010        if self.footer_height > 0 {
2011            let result = &NEWLINES[..self.footer_height];
2012            self.footer_height = 0;
2013            return Some(result);
2014        }
2015
2016        None
2017    }
2018}
2019
2020impl<'a> Iterator for ExcerptChunks<'a> {
2021    type Item = Chunk<'a>;
2022
2023    fn next(&mut self) -> Option<Self::Item> {
2024        if let Some(chunk) = self.content_chunks.next() {
2025            return Some(chunk);
2026        }
2027
2028        if self.footer_height > 0 {
2029            let text = unsafe { str::from_utf8_unchecked(&NEWLINES[..self.footer_height]) };
2030            self.footer_height = 0;
2031            return Some(Chunk {
2032                text,
2033                ..Default::default()
2034            });
2035        }
2036
2037        None
2038    }
2039}
2040
2041impl ToOffset for Point {
2042    fn to_offset<'a>(&self, snapshot: &MultiBufferSnapshot) -> usize {
2043        snapshot.point_to_offset(*self)
2044    }
2045}
2046
2047impl ToOffset for PointUtf16 {
2048    fn to_offset<'a>(&self, snapshot: &MultiBufferSnapshot) -> usize {
2049        snapshot.point_utf16_to_offset(*self)
2050    }
2051}
2052
2053impl ToOffset for usize {
2054    fn to_offset<'a>(&self, snapshot: &MultiBufferSnapshot) -> usize {
2055        assert!(*self <= snapshot.len(), "offset is out of range");
2056        *self
2057    }
2058}
2059
2060impl ToPoint for usize {
2061    fn to_point<'a>(&self, snapshot: &MultiBufferSnapshot) -> Point {
2062        snapshot.offset_to_point(*self)
2063    }
2064}
2065
2066impl ToPoint for Point {
2067    fn to_point<'a>(&self, _: &MultiBufferSnapshot) -> Point {
2068        *self
2069    }
2070}
2071
2072#[cfg(test)]
2073mod tests {
2074    use super::*;
2075    use gpui::MutableAppContext;
2076    use language::{Buffer, Rope};
2077    use rand::prelude::*;
2078    use std::env;
2079    use text::{Point, RandomCharIter};
2080    use util::test::sample_text;
2081
2082    #[gpui::test]
2083    fn test_singleton_multibuffer(cx: &mut MutableAppContext) {
2084        let buffer = cx.add_model(|cx| Buffer::new(0, sample_text(6, 6, 'a'), cx));
2085        let multibuffer = cx.add_model(|cx| MultiBuffer::singleton(buffer.clone(), cx));
2086
2087        let snapshot = multibuffer.read(cx).snapshot(cx);
2088        assert_eq!(snapshot.text(), buffer.read(cx).text());
2089
2090        assert_eq!(
2091            snapshot.buffer_rows(0).collect::<Vec<_>>(),
2092            (0..buffer.read(cx).row_count())
2093                .map(Some)
2094                .collect::<Vec<_>>()
2095        );
2096
2097        buffer.update(cx, |buffer, cx| buffer.edit([1..3], "XXX\n", cx));
2098        let snapshot = multibuffer.read(cx).snapshot(cx);
2099
2100        assert_eq!(snapshot.text(), buffer.read(cx).text());
2101        assert_eq!(
2102            snapshot.buffer_rows(0).collect::<Vec<_>>(),
2103            (0..buffer.read(cx).row_count())
2104                .map(Some)
2105                .collect::<Vec<_>>()
2106        );
2107    }
2108
2109    #[gpui::test]
2110    fn test_excerpt_buffer(cx: &mut MutableAppContext) {
2111        let buffer_1 = cx.add_model(|cx| Buffer::new(0, sample_text(6, 6, 'a'), cx));
2112        let buffer_2 = cx.add_model(|cx| Buffer::new(0, sample_text(6, 6, 'g'), cx));
2113        let multibuffer = cx.add_model(|_| MultiBuffer::new(0));
2114
2115        let subscription = multibuffer.update(cx, |multibuffer, cx| {
2116            let subscription = multibuffer.subscribe();
2117            multibuffer.push_excerpt(
2118                ExcerptProperties {
2119                    buffer: &buffer_1,
2120                    range: Point::new(1, 2)..Point::new(2, 5),
2121                },
2122                cx,
2123            );
2124            assert_eq!(
2125                subscription.consume().into_inner(),
2126                [Edit {
2127                    old: 0..0,
2128                    new: 0..10
2129                }]
2130            );
2131
2132            multibuffer.push_excerpt(
2133                ExcerptProperties {
2134                    buffer: &buffer_1,
2135                    range: Point::new(3, 3)..Point::new(4, 4),
2136                },
2137                cx,
2138            );
2139            multibuffer.push_excerpt(
2140                ExcerptProperties {
2141                    buffer: &buffer_2,
2142                    range: Point::new(3, 1)..Point::new(3, 3),
2143                },
2144                cx,
2145            );
2146            assert_eq!(
2147                subscription.consume().into_inner(),
2148                [Edit {
2149                    old: 10..10,
2150                    new: 10..22
2151                }]
2152            );
2153
2154            subscription
2155        });
2156
2157        let snapshot = multibuffer.read(cx).snapshot(cx);
2158        assert_eq!(
2159            snapshot.text(),
2160            concat!(
2161                "bbbb\n",  // Preserve newlines
2162                "ccccc\n", //
2163                "ddd\n",   //
2164                "eeee\n",  //
2165                "jj"       //
2166            )
2167        );
2168        assert_eq!(
2169            snapshot.buffer_rows(0).collect::<Vec<_>>(),
2170            [Some(1), Some(2), Some(3), Some(4), Some(3)]
2171        );
2172        assert_eq!(
2173            snapshot.buffer_rows(2).collect::<Vec<_>>(),
2174            [Some(3), Some(4), Some(3)]
2175        );
2176        assert_eq!(snapshot.buffer_rows(4).collect::<Vec<_>>(), [Some(3)]);
2177        assert_eq!(snapshot.buffer_rows(5).collect::<Vec<_>>(), []);
2178        assert!(!snapshot.range_contains_excerpt_boundary(Point::new(1, 0)..Point::new(1, 5)));
2179        assert!(snapshot.range_contains_excerpt_boundary(Point::new(1, 0)..Point::new(2, 0)));
2180        assert!(snapshot.range_contains_excerpt_boundary(Point::new(1, 0)..Point::new(4, 0)));
2181        assert!(!snapshot.range_contains_excerpt_boundary(Point::new(2, 0)..Point::new(3, 0)));
2182        assert!(!snapshot.range_contains_excerpt_boundary(Point::new(4, 0)..Point::new(4, 2)));
2183        assert!(!snapshot.range_contains_excerpt_boundary(Point::new(4, 2)..Point::new(4, 2)));
2184
2185        buffer_1.update(cx, |buffer, cx| {
2186            buffer.edit(
2187                [
2188                    Point::new(0, 0)..Point::new(0, 0),
2189                    Point::new(2, 1)..Point::new(2, 3),
2190                ],
2191                "\n",
2192                cx,
2193            );
2194        });
2195
2196        let snapshot = multibuffer.read(cx).snapshot(cx);
2197        assert_eq!(
2198            snapshot.text(),
2199            concat!(
2200                "bbbb\n", // Preserve newlines
2201                "c\n",    //
2202                "cc\n",   //
2203                "ddd\n",  //
2204                "eeee\n", //
2205                "jj"      //
2206            )
2207        );
2208
2209        assert_eq!(
2210            subscription.consume().into_inner(),
2211            [Edit {
2212                old: 6..8,
2213                new: 6..7
2214            }]
2215        );
2216
2217        let snapshot = multibuffer.read(cx).snapshot(cx);
2218        assert_eq!(
2219            snapshot.clip_point(Point::new(0, 5), Bias::Left),
2220            Point::new(0, 4)
2221        );
2222        assert_eq!(
2223            snapshot.clip_point(Point::new(0, 5), Bias::Right),
2224            Point::new(0, 4)
2225        );
2226        assert_eq!(
2227            snapshot.clip_point(Point::new(5, 1), Bias::Right),
2228            Point::new(5, 1)
2229        );
2230        assert_eq!(
2231            snapshot.clip_point(Point::new(5, 2), Bias::Right),
2232            Point::new(5, 2)
2233        );
2234        assert_eq!(
2235            snapshot.clip_point(Point::new(5, 3), Bias::Right),
2236            Point::new(5, 2)
2237        );
2238
2239        let snapshot = multibuffer.update(cx, |multibuffer, cx| {
2240            let buffer_2_excerpt_id = multibuffer.excerpt_ids_for_buffer(&buffer_2)[0].clone();
2241            multibuffer.remove_excerpts(&[buffer_2_excerpt_id], cx);
2242            multibuffer.snapshot(cx)
2243        });
2244
2245        assert_eq!(
2246            snapshot.text(),
2247            concat!(
2248                "bbbb\n", // Preserve newlines
2249                "c\n",    //
2250                "cc\n",   //
2251                "ddd\n",  //
2252                "eeee",   //
2253            )
2254        );
2255    }
2256
2257    #[gpui::test]
2258    fn test_empty_excerpt_buffer(cx: &mut MutableAppContext) {
2259        let multibuffer = cx.add_model(|_| MultiBuffer::new(0));
2260
2261        let snapshot = multibuffer.read(cx).snapshot(cx);
2262        assert_eq!(snapshot.text(), "");
2263        assert_eq!(snapshot.buffer_rows(0).collect::<Vec<_>>(), &[Some(0)]);
2264        assert_eq!(snapshot.buffer_rows(1).collect::<Vec<_>>(), &[]);
2265    }
2266
2267    #[gpui::test]
2268    fn test_singleton_multibuffer_anchors(cx: &mut MutableAppContext) {
2269        let buffer = cx.add_model(|cx| Buffer::new(0, "abcd", cx));
2270        let multibuffer = cx.add_model(|cx| MultiBuffer::singleton(buffer.clone(), cx));
2271        let old_snapshot = multibuffer.read(cx).snapshot(cx);
2272        buffer.update(cx, |buffer, cx| {
2273            buffer.edit([0..0], "X", cx);
2274            buffer.edit([5..5], "Y", cx);
2275        });
2276        let new_snapshot = multibuffer.read(cx).snapshot(cx);
2277
2278        assert_eq!(old_snapshot.text(), "abcd");
2279        assert_eq!(new_snapshot.text(), "XabcdY");
2280
2281        assert_eq!(old_snapshot.anchor_before(0).to_offset(&new_snapshot), 0);
2282        assert_eq!(old_snapshot.anchor_after(0).to_offset(&new_snapshot), 1);
2283        assert_eq!(old_snapshot.anchor_before(4).to_offset(&new_snapshot), 5);
2284        assert_eq!(old_snapshot.anchor_after(4).to_offset(&new_snapshot), 6);
2285    }
2286
2287    #[gpui::test]
2288    fn test_multibuffer_anchors(cx: &mut MutableAppContext) {
2289        let buffer_1 = cx.add_model(|cx| Buffer::new(0, "abcd", cx));
2290        let buffer_2 = cx.add_model(|cx| Buffer::new(0, "efghi", cx));
2291        let multibuffer = cx.add_model(|cx| {
2292            let mut multibuffer = MultiBuffer::new(0);
2293            multibuffer.push_excerpt(
2294                ExcerptProperties {
2295                    buffer: &buffer_1,
2296                    range: 0..4,
2297                },
2298                cx,
2299            );
2300            multibuffer.push_excerpt(
2301                ExcerptProperties {
2302                    buffer: &buffer_2,
2303                    range: 0..5,
2304                },
2305                cx,
2306            );
2307            multibuffer
2308        });
2309        let old_snapshot = multibuffer.read(cx).snapshot(cx);
2310
2311        assert_eq!(old_snapshot.anchor_before(0).to_offset(&old_snapshot), 0);
2312        assert_eq!(old_snapshot.anchor_after(0).to_offset(&old_snapshot), 0);
2313        assert_eq!(Anchor::min().to_offset(&old_snapshot), 0);
2314        assert_eq!(Anchor::min().to_offset(&old_snapshot), 0);
2315        assert_eq!(Anchor::max().to_offset(&old_snapshot), 10);
2316        assert_eq!(Anchor::max().to_offset(&old_snapshot), 10);
2317
2318        buffer_1.update(cx, |buffer, cx| {
2319            buffer.edit([0..0], "W", cx);
2320            buffer.edit([5..5], "X", cx);
2321        });
2322        buffer_2.update(cx, |buffer, cx| {
2323            buffer.edit([0..0], "Y", cx);
2324            buffer.edit([6..0], "Z", cx);
2325        });
2326        let new_snapshot = multibuffer.read(cx).snapshot(cx);
2327
2328        assert_eq!(old_snapshot.text(), "abcd\nefghi");
2329        assert_eq!(new_snapshot.text(), "WabcdX\nYefghiZ");
2330
2331        assert_eq!(old_snapshot.anchor_before(0).to_offset(&new_snapshot), 0);
2332        assert_eq!(old_snapshot.anchor_after(0).to_offset(&new_snapshot), 1);
2333        assert_eq!(old_snapshot.anchor_before(1).to_offset(&new_snapshot), 2);
2334        assert_eq!(old_snapshot.anchor_after(1).to_offset(&new_snapshot), 2);
2335        assert_eq!(old_snapshot.anchor_before(2).to_offset(&new_snapshot), 3);
2336        assert_eq!(old_snapshot.anchor_after(2).to_offset(&new_snapshot), 3);
2337        assert_eq!(old_snapshot.anchor_before(5).to_offset(&new_snapshot), 7);
2338        assert_eq!(old_snapshot.anchor_after(5).to_offset(&new_snapshot), 8);
2339        assert_eq!(old_snapshot.anchor_before(10).to_offset(&new_snapshot), 13);
2340        assert_eq!(old_snapshot.anchor_after(10).to_offset(&new_snapshot), 14);
2341    }
2342
2343    #[gpui::test(iterations = 100)]
2344    fn test_random_excerpts(cx: &mut MutableAppContext, mut rng: StdRng) {
2345        let operations = env::var("OPERATIONS")
2346            .map(|i| i.parse().expect("invalid `OPERATIONS` variable"))
2347            .unwrap_or(10);
2348
2349        let mut buffers: Vec<ModelHandle<Buffer>> = Vec::new();
2350        let list = cx.add_model(|_| MultiBuffer::new(0));
2351        let mut excerpt_ids = Vec::new();
2352        let mut expected_excerpts = Vec::<(ModelHandle<Buffer>, Range<text::Anchor>)>::new();
2353        let mut old_versions = Vec::new();
2354
2355        for _ in 0..operations {
2356            match rng.gen_range(0..100) {
2357                0..=19 if !buffers.is_empty() => {
2358                    let buffer = buffers.choose(&mut rng).unwrap();
2359                    buffer.update(cx, |buf, cx| buf.randomly_edit(&mut rng, 5, cx));
2360                }
2361                20..=29 if !expected_excerpts.is_empty() => {
2362                    let mut ids_to_remove = vec![];
2363                    for _ in 0..rng.gen_range(1..=3) {
2364                        if expected_excerpts.is_empty() {
2365                            break;
2366                        }
2367
2368                        let ix = rng.gen_range(0..expected_excerpts.len());
2369                        ids_to_remove.push(excerpt_ids.remove(ix));
2370                        let (buffer, range) = expected_excerpts.remove(ix);
2371                        let buffer = buffer.read(cx);
2372                        log::info!(
2373                            "Removing excerpt {}: {:?}",
2374                            ix,
2375                            buffer
2376                                .text_for_range(range.to_offset(&buffer))
2377                                .collect::<String>(),
2378                        );
2379                    }
2380                    ids_to_remove.sort_unstable();
2381                    list.update(cx, |list, cx| list.remove_excerpts(&ids_to_remove, cx));
2382                }
2383                _ => {
2384                    let buffer_handle = if buffers.is_empty() || rng.gen_bool(0.4) {
2385                        let base_text = RandomCharIter::new(&mut rng).take(10).collect::<String>();
2386                        buffers.push(cx.add_model(|cx| Buffer::new(0, base_text, cx)));
2387                        buffers.last().unwrap()
2388                    } else {
2389                        buffers.choose(&mut rng).unwrap()
2390                    };
2391
2392                    let buffer = buffer_handle.read(cx);
2393                    let end_ix = buffer.clip_offset(rng.gen_range(0..=buffer.len()), Bias::Right);
2394                    let start_ix = buffer.clip_offset(rng.gen_range(0..=end_ix), Bias::Left);
2395                    let anchor_range = buffer.anchor_before(start_ix)..buffer.anchor_after(end_ix);
2396                    let prev_excerpt_ix = rng.gen_range(0..=expected_excerpts.len());
2397                    let prev_excerpt_id = excerpt_ids
2398                        .get(prev_excerpt_ix)
2399                        .cloned()
2400                        .unwrap_or(ExcerptId::max());
2401                    let excerpt_ix = (prev_excerpt_ix + 1).min(expected_excerpts.len());
2402
2403                    log::info!(
2404                        "Inserting excerpt at {} of {} for buffer {}: {:?}[{:?}] = {:?}",
2405                        excerpt_ix,
2406                        expected_excerpts.len(),
2407                        buffer_handle.id(),
2408                        buffer.text(),
2409                        start_ix..end_ix,
2410                        &buffer.text()[start_ix..end_ix]
2411                    );
2412
2413                    let excerpt_id = list.update(cx, |list, cx| {
2414                        list.insert_excerpt_after(
2415                            &prev_excerpt_id,
2416                            ExcerptProperties {
2417                                buffer: &buffer_handle,
2418                                range: start_ix..end_ix,
2419                            },
2420                            cx,
2421                        )
2422                    });
2423
2424                    excerpt_ids.insert(excerpt_ix, excerpt_id);
2425                    expected_excerpts.insert(excerpt_ix, (buffer_handle.clone(), anchor_range));
2426                }
2427            }
2428
2429            if rng.gen_bool(0.3) {
2430                list.update(cx, |list, cx| {
2431                    old_versions.push((list.snapshot(cx), list.subscribe()));
2432                })
2433            }
2434
2435            let snapshot = list.read(cx).snapshot(cx);
2436
2437            let mut excerpt_starts = Vec::new();
2438            let mut expected_text = String::new();
2439            let mut expected_buffer_rows = Vec::new();
2440            for (buffer, range) in &expected_excerpts {
2441                let buffer = buffer.read(cx);
2442                let buffer_range = range.to_offset(buffer);
2443
2444                excerpt_starts.push(TextSummary::from(expected_text.as_str()));
2445                expected_text.extend(buffer.text_for_range(buffer_range.clone()));
2446                expected_text.push('\n');
2447
2448                let buffer_row_range = buffer.offset_to_point(buffer_range.start).row
2449                    ..=buffer.offset_to_point(buffer_range.end).row;
2450                for row in buffer_row_range {
2451                    expected_buffer_rows.push(Some(row));
2452                }
2453            }
2454            // Remove final trailing newline.
2455            if !expected_excerpts.is_empty() {
2456                expected_text.pop();
2457            }
2458
2459            // Always report one buffer row
2460            if expected_buffer_rows.is_empty() {
2461                expected_buffer_rows.push(Some(0));
2462            }
2463
2464            assert_eq!(snapshot.text(), expected_text);
2465            log::info!("MultiBuffer text: {:?}", expected_text);
2466
2467            assert_eq!(
2468                snapshot.buffer_rows(0).collect::<Vec<_>>(),
2469                expected_buffer_rows,
2470            );
2471
2472            for _ in 0..5 {
2473                let start_row = rng.gen_range(0..=expected_buffer_rows.len());
2474                assert_eq!(
2475                    snapshot.buffer_rows(start_row as u32).collect::<Vec<_>>(),
2476                    &expected_buffer_rows[start_row..],
2477                    "buffer_rows({})",
2478                    start_row
2479                );
2480            }
2481
2482            assert_eq!(
2483                snapshot.max_buffer_row(),
2484                expected_buffer_rows
2485                    .into_iter()
2486                    .filter_map(|r| r)
2487                    .max()
2488                    .unwrap()
2489            );
2490
2491            let mut excerpt_starts = excerpt_starts.into_iter();
2492            for (buffer, range) in &expected_excerpts {
2493                let buffer_id = buffer.id();
2494                let buffer = buffer.read(cx);
2495                let buffer_range = range.to_offset(buffer);
2496                let buffer_start_point = buffer.offset_to_point(buffer_range.start);
2497                let buffer_start_point_utf16 =
2498                    buffer.text_summary_for_range::<PointUtf16, _>(0..buffer_range.start);
2499
2500                let excerpt_start = excerpt_starts.next().unwrap();
2501                let mut offset = excerpt_start.bytes;
2502                let mut buffer_offset = buffer_range.start;
2503                let mut point = excerpt_start.lines;
2504                let mut buffer_point = buffer_start_point;
2505                let mut point_utf16 = excerpt_start.lines_utf16;
2506                let mut buffer_point_utf16 = buffer_start_point_utf16;
2507                for ch in buffer
2508                    .snapshot()
2509                    .chunks(buffer_range.clone(), None)
2510                    .flat_map(|c| c.text.chars())
2511                {
2512                    for _ in 0..ch.len_utf8() {
2513                        let left_offset = snapshot.clip_offset(offset, Bias::Left);
2514                        let right_offset = snapshot.clip_offset(offset, Bias::Right);
2515                        let buffer_left_offset = buffer.clip_offset(buffer_offset, Bias::Left);
2516                        let buffer_right_offset = buffer.clip_offset(buffer_offset, Bias::Right);
2517                        assert_eq!(
2518                            left_offset,
2519                            excerpt_start.bytes + (buffer_left_offset - buffer_range.start),
2520                            "clip_offset({:?}, Left). buffer: {:?}, buffer offset: {:?}",
2521                            offset,
2522                            buffer_id,
2523                            buffer_offset,
2524                        );
2525                        assert_eq!(
2526                            right_offset,
2527                            excerpt_start.bytes + (buffer_right_offset - buffer_range.start),
2528                            "clip_offset({:?}, Right). buffer: {:?}, buffer offset: {:?}",
2529                            offset,
2530                            buffer_id,
2531                            buffer_offset,
2532                        );
2533
2534                        let left_point = snapshot.clip_point(point, Bias::Left);
2535                        let right_point = snapshot.clip_point(point, Bias::Right);
2536                        let buffer_left_point = buffer.clip_point(buffer_point, Bias::Left);
2537                        let buffer_right_point = buffer.clip_point(buffer_point, Bias::Right);
2538                        assert_eq!(
2539                            left_point,
2540                            excerpt_start.lines + (buffer_left_point - buffer_start_point),
2541                            "clip_point({:?}, Left). buffer: {:?}, buffer point: {:?}",
2542                            point,
2543                            buffer_id,
2544                            buffer_point,
2545                        );
2546                        assert_eq!(
2547                            right_point,
2548                            excerpt_start.lines + (buffer_right_point - buffer_start_point),
2549                            "clip_point({:?}, Right). buffer: {:?}, buffer point: {:?}",
2550                            point,
2551                            buffer_id,
2552                            buffer_point,
2553                        );
2554
2555                        assert_eq!(
2556                            snapshot.point_to_offset(left_point),
2557                            left_offset,
2558                            "point_to_offset({:?})",
2559                            left_point,
2560                        );
2561                        assert_eq!(
2562                            snapshot.offset_to_point(left_offset),
2563                            left_point,
2564                            "offset_to_point({:?})",
2565                            left_offset,
2566                        );
2567
2568                        offset += 1;
2569                        buffer_offset += 1;
2570                        if ch == '\n' {
2571                            point += Point::new(1, 0);
2572                            buffer_point += Point::new(1, 0);
2573                        } else {
2574                            point += Point::new(0, 1);
2575                            buffer_point += Point::new(0, 1);
2576                        }
2577                    }
2578
2579                    for _ in 0..ch.len_utf16() {
2580                        let left_point_utf16 = snapshot.clip_point_utf16(point_utf16, Bias::Left);
2581                        let right_point_utf16 = snapshot.clip_point_utf16(point_utf16, Bias::Right);
2582                        let buffer_left_point_utf16 =
2583                            buffer.clip_point_utf16(buffer_point_utf16, Bias::Left);
2584                        let buffer_right_point_utf16 =
2585                            buffer.clip_point_utf16(buffer_point_utf16, Bias::Right);
2586                        assert_eq!(
2587                            left_point_utf16,
2588                            excerpt_start.lines_utf16
2589                                + (buffer_left_point_utf16 - buffer_start_point_utf16),
2590                            "clip_point_utf16({:?}, Left). buffer: {:?}, buffer point_utf16: {:?}",
2591                            point_utf16,
2592                            buffer_id,
2593                            buffer_point_utf16,
2594                        );
2595                        assert_eq!(
2596                            right_point_utf16,
2597                            excerpt_start.lines_utf16
2598                                + (buffer_right_point_utf16 - buffer_start_point_utf16),
2599                            "clip_point_utf16({:?}, Right). buffer: {:?}, buffer point_utf16: {:?}",
2600                            point_utf16,
2601                            buffer_id,
2602                            buffer_point_utf16,
2603                        );
2604
2605                        if ch == '\n' {
2606                            point_utf16 += PointUtf16::new(1, 0);
2607                            buffer_point_utf16 += PointUtf16::new(1, 0);
2608                        } else {
2609                            point_utf16 += PointUtf16::new(0, 1);
2610                            buffer_point_utf16 += PointUtf16::new(0, 1);
2611                        }
2612                    }
2613                }
2614            }
2615
2616            for (row, line) in expected_text.split('\n').enumerate() {
2617                assert_eq!(
2618                    snapshot.line_len(row as u32),
2619                    line.len() as u32,
2620                    "line_len({}).",
2621                    row
2622                );
2623            }
2624
2625            let text_rope = Rope::from(expected_text.as_str());
2626            for _ in 0..10 {
2627                let end_ix = text_rope.clip_offset(rng.gen_range(0..=text_rope.len()), Bias::Right);
2628                let start_ix = text_rope.clip_offset(rng.gen_range(0..=end_ix), Bias::Left);
2629
2630                assert_eq!(
2631                    snapshot
2632                        .text_for_range(start_ix..end_ix)
2633                        .collect::<String>(),
2634                    &expected_text[start_ix..end_ix],
2635                    "incorrect text for range {:?}",
2636                    start_ix..end_ix
2637                );
2638
2639                let expected_summary = TextSummary::from(&expected_text[start_ix..end_ix]);
2640                assert_eq!(
2641                    snapshot.text_summary_for_range::<TextSummary, _>(start_ix..end_ix),
2642                    expected_summary,
2643                    "incorrect summary for range {:?}",
2644                    start_ix..end_ix
2645                );
2646            }
2647
2648            for _ in 0..10 {
2649                let end_ix = text_rope.clip_offset(rng.gen_range(0..=text_rope.len()), Bias::Right);
2650                assert_eq!(
2651                    snapshot.reversed_chars_at(end_ix).collect::<String>(),
2652                    expected_text[..end_ix].chars().rev().collect::<String>(),
2653                );
2654            }
2655
2656            for _ in 0..10 {
2657                let end_ix = rng.gen_range(0..=text_rope.len());
2658                let start_ix = rng.gen_range(0..=end_ix);
2659                assert_eq!(
2660                    snapshot
2661                        .bytes_in_range(start_ix..end_ix)
2662                        .flatten()
2663                        .copied()
2664                        .collect::<Vec<_>>(),
2665                    expected_text.as_bytes()[start_ix..end_ix].to_vec(),
2666                    "bytes_in_range({:?})",
2667                    start_ix..end_ix,
2668                );
2669            }
2670        }
2671
2672        let snapshot = list.read(cx).snapshot(cx);
2673        for (old_snapshot, subscription) in old_versions {
2674            let edits = subscription.consume().into_inner();
2675
2676            log::info!(
2677                "applying subscription edits to old text: {:?}: {:?}",
2678                old_snapshot.text(),
2679                edits,
2680            );
2681
2682            let mut text = old_snapshot.text();
2683            for edit in edits {
2684                let new_text: String = snapshot.text_for_range(edit.new.clone()).collect();
2685                text.replace_range(edit.new.start..edit.new.start + edit.old.len(), &new_text);
2686            }
2687            assert_eq!(text.to_string(), snapshot.text());
2688        }
2689    }
2690
2691    #[gpui::test]
2692    fn test_history(cx: &mut MutableAppContext) {
2693        let buffer_1 = cx.add_model(|cx| Buffer::new(0, "1234", cx));
2694        let buffer_2 = cx.add_model(|cx| Buffer::new(0, "5678", cx));
2695        let multibuffer = cx.add_model(|_| MultiBuffer::new(0));
2696        let group_interval = multibuffer.read(cx).history.group_interval;
2697        multibuffer.update(cx, |multibuffer, cx| {
2698            multibuffer.push_excerpt(
2699                ExcerptProperties {
2700                    buffer: &buffer_1,
2701                    range: 0..buffer_1.read(cx).len(),
2702                },
2703                cx,
2704            );
2705            multibuffer.push_excerpt(
2706                ExcerptProperties {
2707                    buffer: &buffer_2,
2708                    range: 0..buffer_2.read(cx).len(),
2709                },
2710                cx,
2711            );
2712        });
2713
2714        let mut now = Instant::now();
2715
2716        multibuffer.update(cx, |multibuffer, cx| {
2717            multibuffer.start_transaction_at(now, cx);
2718            multibuffer.edit(
2719                [
2720                    Point::new(0, 0)..Point::new(0, 0),
2721                    Point::new(1, 0)..Point::new(1, 0),
2722                ],
2723                "A",
2724                cx,
2725            );
2726            multibuffer.edit(
2727                [
2728                    Point::new(0, 1)..Point::new(0, 1),
2729                    Point::new(1, 1)..Point::new(1, 1),
2730                ],
2731                "B",
2732                cx,
2733            );
2734            multibuffer.end_transaction_at(now, cx);
2735            assert_eq!(multibuffer.read(cx).text(), "AB1234\nAB5678");
2736
2737            now += 2 * group_interval;
2738            multibuffer.start_transaction_at(now, cx);
2739            multibuffer.edit([2..2], "C", cx);
2740            multibuffer.end_transaction_at(now, cx);
2741            assert_eq!(multibuffer.read(cx).text(), "ABC1234\nAB5678");
2742
2743            multibuffer.undo(cx);
2744            assert_eq!(multibuffer.read(cx).text(), "AB1234\nAB5678");
2745
2746            multibuffer.undo(cx);
2747            assert_eq!(multibuffer.read(cx).text(), "1234\n5678");
2748
2749            multibuffer.redo(cx);
2750            assert_eq!(multibuffer.read(cx).text(), "AB1234\nAB5678");
2751
2752            multibuffer.redo(cx);
2753            assert_eq!(multibuffer.read(cx).text(), "ABC1234\nAB5678");
2754
2755            buffer_1.update(cx, |buffer_1, cx| buffer_1.undo(cx));
2756            assert_eq!(multibuffer.read(cx).text(), "AB1234\nAB5678");
2757
2758            multibuffer.undo(cx);
2759            assert_eq!(multibuffer.read(cx).text(), "1234\n5678");
2760
2761            multibuffer.redo(cx);
2762            assert_eq!(multibuffer.read(cx).text(), "AB1234\nAB5678");
2763
2764            multibuffer.redo(cx);
2765            assert_eq!(multibuffer.read(cx).text(), "ABC1234\nAB5678");
2766
2767            multibuffer.undo(cx);
2768            assert_eq!(multibuffer.read(cx).text(), "AB1234\nAB5678");
2769
2770            buffer_1.update(cx, |buffer_1, cx| buffer_1.redo(cx));
2771            assert_eq!(multibuffer.read(cx).text(), "ABC1234\nAB5678");
2772
2773            multibuffer.undo(cx);
2774            assert_eq!(multibuffer.read(cx).text(), "C1234\n5678");
2775        });
2776    }
2777}