multi_buffer.rs

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