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