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