multi_buffer.rs

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