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, 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 buffer_start = excerpt.range.start.to_offset(&excerpt.buffer);
1206            let overshoot = offset.saturating_sub(start_after_header);
1207            Anchor {
1208                excerpt_id: excerpt.id.clone(),
1209                text_anchor: excerpt.buffer.anchor_at(buffer_start + overshoot, bias),
1210            }
1211        } else if offset == 0 && bias == Bias::Left {
1212            Anchor::min()
1213        } else {
1214            Anchor::max()
1215        }
1216    }
1217
1218    pub fn parse_count(&self) -> usize {
1219        self.parse_count
1220    }
1221
1222    pub fn enclosing_bracket_ranges<T: ToOffset>(
1223        &self,
1224        range: Range<T>,
1225    ) -> Option<(Range<usize>, Range<usize>)> {
1226        let range = range.start.to_offset(self)..range.end.to_offset(self);
1227        self.as_singleton().unwrap().enclosing_bracket_ranges(range)
1228    }
1229
1230    pub fn diagnostics_update_count(&self) -> usize {
1231        self.diagnostics_update_count
1232    }
1233
1234    pub fn language(&self) -> Option<&Arc<Language>> {
1235        self.excerpts
1236            .iter()
1237            .next()
1238            .and_then(|excerpt| excerpt.buffer.language())
1239    }
1240
1241    pub fn diagnostic_group<'a, O>(
1242        &'a self,
1243        group_id: usize,
1244    ) -> impl Iterator<Item = DiagnosticEntry<O>> + 'a
1245    where
1246        O: text::FromAnchor + 'a,
1247    {
1248        self.as_singleton().unwrap().diagnostic_group(group_id)
1249    }
1250
1251    pub fn diagnostics_in_range<'a, T, O>(
1252        &'a self,
1253        range: Range<T>,
1254    ) -> impl Iterator<Item = DiagnosticEntry<O>> + 'a
1255    where
1256        T: 'a + ToOffset,
1257        O: 'a + text::FromAnchor,
1258    {
1259        let range = range.start.to_offset(self)..range.end.to_offset(self);
1260        self.as_singleton().unwrap().diagnostics_in_range(range)
1261    }
1262
1263    pub fn range_for_syntax_ancestor<T: ToOffset>(&self, range: Range<T>) -> Option<Range<usize>> {
1264        let range = range.start.to_offset(self)..range.end.to_offset(self);
1265        self.as_singleton()
1266            .unwrap()
1267            .range_for_syntax_ancestor(range)
1268    }
1269
1270    fn buffer_snapshot_for_excerpt<'a>(
1271        &'a self,
1272        excerpt_id: &'a ExcerptId,
1273    ) -> Option<&'a BufferSnapshot> {
1274        let mut cursor = self.excerpts.cursor::<Option<&ExcerptId>>();
1275        cursor.seek(&Some(excerpt_id), Bias::Left, &());
1276        if let Some(excerpt) = cursor.item() {
1277            if excerpt.id == *excerpt_id {
1278                return Some(&excerpt.buffer);
1279            }
1280        }
1281        None
1282    }
1283
1284    pub fn remote_selections_in_range<'a>(
1285        &'a self,
1286        range: &'a Range<Anchor>,
1287    ) -> impl 'a + Iterator<Item = (ReplicaId, Selection<Anchor>)> {
1288        let mut cursor = self.excerpts.cursor::<Option<&ExcerptId>>();
1289        cursor.seek(&Some(&range.start.excerpt_id), Bias::Left, &());
1290        cursor
1291            .take_while(move |excerpt| excerpt.id <= range.end.excerpt_id)
1292            .flat_map(move |excerpt| {
1293                let mut query_range = excerpt.range.start.clone()..excerpt.range.end.clone();
1294                if excerpt.id == range.start.excerpt_id {
1295                    query_range.start = range.start.text_anchor.clone();
1296                }
1297                if excerpt.id == range.end.excerpt_id {
1298                    query_range.end = range.end.text_anchor.clone();
1299                }
1300
1301                excerpt
1302                    .buffer
1303                    .remote_selections_in_range(query_range)
1304                    .flat_map(move |(replica_id, selections)| {
1305                        selections.map(move |selection| {
1306                            let mut start = Anchor {
1307                                excerpt_id: excerpt.id.clone(),
1308                                text_anchor: selection.start.clone(),
1309                            };
1310                            let mut end = Anchor {
1311                                excerpt_id: excerpt.id.clone(),
1312                                text_anchor: selection.end.clone(),
1313                            };
1314                            if range.start.cmp(&start, self).unwrap().is_gt() {
1315                                start = range.start.clone();
1316                            }
1317                            if range.end.cmp(&end, self).unwrap().is_lt() {
1318                                end = range.end.clone();
1319                            }
1320
1321                            (
1322                                replica_id,
1323                                Selection {
1324                                    id: selection.id,
1325                                    start,
1326                                    end,
1327                                    reversed: selection.reversed,
1328                                    goal: selection.goal,
1329                                },
1330                            )
1331                        })
1332                    })
1333            })
1334    }
1335}
1336
1337impl History {
1338    fn start_transaction(&mut self, now: Instant) -> Option<TransactionId> {
1339        self.transaction_depth += 1;
1340        if self.transaction_depth == 1 {
1341            let id = post_inc(&mut self.next_transaction_id);
1342            self.undo_stack.push(Transaction {
1343                id,
1344                buffer_transactions: Default::default(),
1345                first_edit_at: now,
1346                last_edit_at: now,
1347            });
1348            Some(id)
1349        } else {
1350            None
1351        }
1352    }
1353
1354    fn end_transaction(
1355        &mut self,
1356        now: Instant,
1357        buffer_transactions: HashSet<(usize, TransactionId)>,
1358    ) -> bool {
1359        assert_ne!(self.transaction_depth, 0);
1360        self.transaction_depth -= 1;
1361        if self.transaction_depth == 0 {
1362            if buffer_transactions.is_empty() {
1363                self.undo_stack.pop();
1364                false
1365            } else {
1366                let transaction = self.undo_stack.last_mut().unwrap();
1367                transaction.last_edit_at = now;
1368                transaction.buffer_transactions.extend(buffer_transactions);
1369                true
1370            }
1371        } else {
1372            false
1373        }
1374    }
1375
1376    fn pop_undo(&mut self) -> Option<&Transaction> {
1377        assert_eq!(self.transaction_depth, 0);
1378        if let Some(transaction) = self.undo_stack.pop() {
1379            self.redo_stack.push(transaction);
1380            self.redo_stack.last()
1381        } else {
1382            None
1383        }
1384    }
1385
1386    fn pop_redo(&mut self) -> Option<&Transaction> {
1387        assert_eq!(self.transaction_depth, 0);
1388        if let Some(transaction) = self.redo_stack.pop() {
1389            self.undo_stack.push(transaction);
1390            self.undo_stack.last()
1391        } else {
1392            None
1393        }
1394    }
1395
1396    fn group(&mut self) -> Option<TransactionId> {
1397        let mut new_len = self.undo_stack.len();
1398        let mut transactions = self.undo_stack.iter_mut();
1399
1400        if let Some(mut transaction) = transactions.next_back() {
1401            while let Some(prev_transaction) = transactions.next_back() {
1402                if transaction.first_edit_at - prev_transaction.last_edit_at <= self.group_interval
1403                {
1404                    transaction = prev_transaction;
1405                    new_len -= 1;
1406                } else {
1407                    break;
1408                }
1409            }
1410        }
1411
1412        let (transactions_to_keep, transactions_to_merge) = self.undo_stack.split_at_mut(new_len);
1413        if let Some(last_transaction) = transactions_to_keep.last_mut() {
1414            if let Some(transaction) = transactions_to_merge.last() {
1415                last_transaction.last_edit_at = transaction.last_edit_at;
1416            }
1417        }
1418
1419        self.undo_stack.truncate(new_len);
1420        self.undo_stack.last().map(|t| t.id)
1421    }
1422}
1423
1424impl Excerpt {
1425    fn new(
1426        id: ExcerptId,
1427        buffer_id: usize,
1428        buffer: BufferSnapshot,
1429        range: Range<text::Anchor>,
1430        header_height: u8,
1431        render_header: Option<RenderHeaderFn>,
1432        has_trailing_newline: bool,
1433    ) -> Self {
1434        let mut text_summary =
1435            buffer.text_summary_for_range::<TextSummary, _>(range.to_offset(&buffer));
1436        if header_height > 0 {
1437            text_summary.first_line_chars = 0;
1438            text_summary.lines.row += header_height as u32;
1439            text_summary.lines_utf16.row += header_height as u32;
1440            text_summary.bytes += header_height as usize;
1441            text_summary.longest_row += header_height as u32;
1442        }
1443        if has_trailing_newline {
1444            text_summary.last_line_chars = 0;
1445            text_summary.lines.row += 1;
1446            text_summary.lines.column = 0;
1447            text_summary.lines_utf16.row += 1;
1448            text_summary.lines_utf16.column = 0;
1449            text_summary.bytes += 1;
1450        }
1451
1452        Excerpt {
1453            id,
1454            buffer_id,
1455            buffer,
1456            range,
1457            text_summary,
1458            header_height,
1459            render_header,
1460            has_trailing_newline,
1461        }
1462    }
1463
1464    fn header_summary(&self) -> TextSummary {
1465        TextSummary {
1466            bytes: self.header_height as usize,
1467            lines: Point::new(self.header_height as u32, 0),
1468            lines_utf16: PointUtf16::new(self.header_height as u32, 0),
1469            first_line_chars: 0,
1470            last_line_chars: 0,
1471            longest_row: 0,
1472            longest_row_chars: 0,
1473        }
1474    }
1475}
1476
1477impl sum_tree::Item for Excerpt {
1478    type Summary = ExcerptSummary;
1479
1480    fn summary(&self) -> Self::Summary {
1481        ExcerptSummary {
1482            excerpt_id: self.id.clone(),
1483            text: self.text_summary.clone(),
1484        }
1485    }
1486}
1487
1488impl sum_tree::Summary for ExcerptSummary {
1489    type Context = ();
1490
1491    fn add_summary(&mut self, summary: &Self, _: &()) {
1492        debug_assert!(summary.excerpt_id > self.excerpt_id);
1493        self.excerpt_id = summary.excerpt_id.clone();
1494        self.text.add_summary(&summary.text, &());
1495    }
1496}
1497
1498impl<'a> sum_tree::Dimension<'a, ExcerptSummary> for TextSummary {
1499    fn add_summary(&mut self, summary: &'a ExcerptSummary, _: &()) {
1500        *self += &summary.text;
1501    }
1502}
1503
1504impl<'a> sum_tree::Dimension<'a, ExcerptSummary> for usize {
1505    fn add_summary(&mut self, summary: &'a ExcerptSummary, _: &()) {
1506        *self += summary.text.bytes;
1507    }
1508}
1509
1510impl<'a> sum_tree::SeekTarget<'a, ExcerptSummary, ExcerptSummary> for usize {
1511    fn cmp(&self, cursor_location: &ExcerptSummary, _: &()) -> cmp::Ordering {
1512        Ord::cmp(self, &cursor_location.text.bytes)
1513    }
1514}
1515
1516impl<'a> sum_tree::SeekTarget<'a, ExcerptSummary, ExcerptSummary> for Option<&'a ExcerptId> {
1517    fn cmp(&self, cursor_location: &ExcerptSummary, _: &()) -> cmp::Ordering {
1518        Ord::cmp(self, &Some(&cursor_location.excerpt_id))
1519    }
1520}
1521
1522impl<'a> sum_tree::Dimension<'a, ExcerptSummary> for Point {
1523    fn add_summary(&mut self, summary: &'a ExcerptSummary, _: &()) {
1524        *self += summary.text.lines;
1525    }
1526}
1527
1528impl<'a> sum_tree::Dimension<'a, ExcerptSummary> for PointUtf16 {
1529    fn add_summary(&mut self, summary: &'a ExcerptSummary, _: &()) {
1530        *self += summary.text.lines_utf16
1531    }
1532}
1533
1534impl<'a> sum_tree::Dimension<'a, ExcerptSummary> for Option<&'a ExcerptId> {
1535    fn add_summary(&mut self, summary: &'a ExcerptSummary, _: &()) {
1536        *self = Some(&summary.excerpt_id);
1537    }
1538}
1539
1540impl<'a> MultiBufferChunks<'a> {
1541    pub fn offset(&self) -> usize {
1542        self.range.start
1543    }
1544
1545    pub fn seek(&mut self, offset: usize) {
1546        self.range.start = offset;
1547        self.cursor.seek_forward(&offset, Bias::Right, &());
1548        self.header_height = 0;
1549        self.excerpt_chunks = None;
1550        if let Some(excerpt) = self.cursor.item() {
1551            let buffer_range = excerpt.range.to_offset(&excerpt.buffer);
1552            self.header_height = excerpt.header_height;
1553            self.has_trailing_newline = excerpt.has_trailing_newline;
1554
1555            let buffer_start;
1556            let start_overshoot = self.range.start - self.cursor.start();
1557            if start_overshoot < excerpt.header_height as usize {
1558                self.header_height -= start_overshoot as u8;
1559                buffer_start = buffer_range.start;
1560            } else {
1561                buffer_start =
1562                    buffer_range.start + start_overshoot - excerpt.header_height as usize;
1563                self.header_height = 0;
1564            }
1565
1566            let buffer_end;
1567            let end_overshoot = self.range.end - self.cursor.start();
1568            if end_overshoot < excerpt.header_height as usize {
1569                self.header_height -= excerpt.header_height - end_overshoot as u8;
1570                buffer_end = buffer_start;
1571            } else {
1572                buffer_end = cmp::min(
1573                    buffer_range.end,
1574                    buffer_range.start + end_overshoot - excerpt.header_height as usize,
1575                );
1576            }
1577
1578            self.excerpt_chunks = Some(excerpt.buffer.chunks(buffer_start..buffer_end, self.theme));
1579        }
1580    }
1581}
1582
1583impl<'a> Iterator for MultiBufferChunks<'a> {
1584    type Item = Chunk<'a>;
1585
1586    fn next(&mut self) -> Option<Self::Item> {
1587        loop {
1588            if self.header_height > 0 {
1589                let chunk = Chunk {
1590                    text: unsafe {
1591                        std::str::from_utf8_unchecked(&NEWLINES[..self.header_height as usize])
1592                    },
1593                    ..Default::default()
1594                };
1595                self.range.start += self.header_height as usize;
1596                self.header_height = 0;
1597                return Some(chunk);
1598            }
1599
1600            if let Some(excerpt_chunks) = self.excerpt_chunks.as_mut() {
1601                if let Some(chunk) = excerpt_chunks.next() {
1602                    self.range.start += chunk.text.len();
1603                    return Some(chunk);
1604                }
1605                self.excerpt_chunks.take();
1606                if self.has_trailing_newline && self.cursor.end(&()) <= self.range.end {
1607                    self.range.start += 1;
1608                    return Some(Chunk {
1609                        text: "\n",
1610                        ..Default::default()
1611                    });
1612                }
1613            }
1614
1615            self.cursor.next(&());
1616            if *self.cursor.start() >= self.range.end {
1617                return None;
1618            }
1619
1620            let excerpt = self.cursor.item()?;
1621            let buffer_range = excerpt.range.to_offset(&excerpt.buffer);
1622
1623            let buffer_end = cmp::min(
1624                buffer_range.end,
1625                buffer_range.start + self.range.end
1626                    - excerpt.header_height as usize
1627                    - self.cursor.start(),
1628            );
1629
1630            self.header_height = excerpt.header_height;
1631            self.has_trailing_newline = excerpt.has_trailing_newline;
1632            self.excerpt_chunks = Some(
1633                excerpt
1634                    .buffer
1635                    .chunks(buffer_range.start..buffer_end, self.theme),
1636            );
1637        }
1638    }
1639}
1640
1641impl<'a> Iterator for MultiBufferBytes<'a> {
1642    type Item = &'a [u8];
1643
1644    fn next(&mut self) -> Option<Self::Item> {
1645        self.chunks.next().map(|chunk| chunk.text.as_bytes())
1646    }
1647}
1648
1649impl<'a> io::Read for MultiBufferBytes<'a> {
1650    fn read(&mut self, _: &mut [u8]) -> io::Result<usize> {
1651        todo!()
1652    }
1653}
1654
1655impl ToOffset for Point {
1656    fn to_offset<'a>(&self, snapshot: &MultiBufferSnapshot) -> usize {
1657        snapshot.point_to_offset(*self)
1658    }
1659}
1660
1661impl ToOffset for PointUtf16 {
1662    fn to_offset<'a>(&self, snapshot: &MultiBufferSnapshot) -> usize {
1663        snapshot.point_utf16_to_offset(*self)
1664    }
1665}
1666
1667impl ToOffset for usize {
1668    fn to_offset<'a>(&self, snapshot: &MultiBufferSnapshot) -> usize {
1669        assert!(*self <= snapshot.len(), "offset is out of range");
1670        *self
1671    }
1672}
1673
1674impl ToPoint for usize {
1675    fn to_point<'a>(&self, snapshot: &MultiBufferSnapshot) -> Point {
1676        snapshot.offset_to_point(*self)
1677    }
1678}
1679
1680impl ToPoint for Point {
1681    fn to_point<'a>(&self, _: &MultiBufferSnapshot) -> Point {
1682        *self
1683    }
1684}
1685
1686#[cfg(test)]
1687mod tests {
1688    use super::*;
1689    use gpui::{elements::Empty, Element, MutableAppContext};
1690    use language::Buffer;
1691    use rand::prelude::*;
1692    use std::env;
1693    use text::{Point, RandomCharIter};
1694    use util::test::sample_text;
1695
1696    #[gpui::test]
1697    fn test_singleton_multibuffer(cx: &mut MutableAppContext) {
1698        let buffer = cx.add_model(|cx| Buffer::new(0, sample_text(6, 6, 'a'), cx));
1699        let multibuffer = cx.add_model(|cx| MultiBuffer::singleton(buffer.clone(), cx));
1700        assert_eq!(
1701            multibuffer.read(cx).snapshot(cx).text(),
1702            buffer.read(cx).text()
1703        );
1704
1705        buffer.update(cx, |buffer, cx| buffer.edit([1..3], "XXX", cx));
1706        assert_eq!(
1707            multibuffer.read(cx).snapshot(cx).text(),
1708            buffer.read(cx).text()
1709        );
1710    }
1711
1712    #[gpui::test]
1713    fn test_excerpt_buffer(cx: &mut MutableAppContext) {
1714        let buffer_1 = cx.add_model(|cx| Buffer::new(0, sample_text(6, 6, 'a'), cx));
1715        let buffer_2 = cx.add_model(|cx| Buffer::new(0, sample_text(6, 6, 'g'), cx));
1716        let multibuffer = cx.add_model(|_| MultiBuffer::new(0));
1717
1718        let subscription = multibuffer.update(cx, |multibuffer, cx| {
1719            let subscription = multibuffer.subscribe();
1720            multibuffer.push_excerpt(
1721                ExcerptProperties {
1722                    buffer: &buffer_1,
1723                    range: Point::new(1, 2)..Point::new(2, 5),
1724                    header_height: 2,
1725                    render_header: Some(Arc::new(|_| Empty::new().named("header 1"))),
1726                },
1727                cx,
1728            );
1729            assert_eq!(
1730                subscription.consume().into_inner(),
1731                [Edit {
1732                    old: 0..0,
1733                    new: 0..13
1734                }]
1735            );
1736
1737            multibuffer.push_excerpt(
1738                ExcerptProperties {
1739                    buffer: &buffer_1,
1740                    range: Point::new(3, 3)..Point::new(4, 4),
1741                    header_height: 1,
1742                    render_header: Some(Arc::new(|_| Empty::new().named("header 2"))),
1743                },
1744                cx,
1745            );
1746            multibuffer.push_excerpt(
1747                ExcerptProperties {
1748                    buffer: &buffer_2,
1749                    range: Point::new(3, 1)..Point::new(3, 3),
1750                    header_height: 3,
1751                    render_header: Some(Arc::new(|_| Empty::new().named("header 3"))),
1752                },
1753                cx,
1754            );
1755            assert_eq!(
1756                subscription.consume().into_inner(),
1757                [Edit {
1758                    old: 13..13,
1759                    new: 13..29
1760                }]
1761            );
1762
1763            subscription
1764        });
1765
1766        assert_eq!(
1767            multibuffer.read(cx).snapshot(cx).text(),
1768            concat!(
1769                "\n",      // Preserve newlines
1770                "\n",      //
1771                "bbbb\n",  //
1772                "ccccc\n", //
1773                "\n",      //
1774                "ddd\n",   //
1775                "eeee\n",  //
1776                "\n",      //
1777                "\n",      //
1778                "\n",      //
1779                "jj\n"     //
1780            )
1781        );
1782
1783        {
1784            let snapshot = multibuffer.read(cx).read(cx);
1785            assert_eq!(
1786                snapshot
1787                    .excerpt_headers_in_range(0..snapshot.max_point().row + 1)
1788                    .map(|(rows, render)| (rows, render(cx).name().unwrap().to_string()))
1789                    .collect::<Vec<_>>(),
1790                &[
1791                    (0..2, "header 1".into()),
1792                    (4..5, "header 2".into()),
1793                    (7..10, "header 3".into())
1794                ]
1795            );
1796
1797            assert_eq!(
1798                snapshot
1799                    .excerpt_headers_in_range(1..5)
1800                    .map(|(rows, render)| (rows, render(cx).name().unwrap().to_string()))
1801                    .collect::<Vec<_>>(),
1802                &[(0..2, "header 1".into()), (4..5, "header 2".into())]
1803            );
1804
1805            assert_eq!(
1806                snapshot
1807                    .excerpt_headers_in_range(2..8)
1808                    .map(|(rows, render)| (rows, render(cx).name().unwrap().to_string()))
1809                    .collect::<Vec<_>>(),
1810                &[(4..5, "header 2".into()), (7..10, "header 3".into())]
1811            );
1812        }
1813
1814        buffer_1.update(cx, |buffer, cx| {
1815            buffer.edit(
1816                [
1817                    Point::new(0, 0)..Point::new(0, 0),
1818                    Point::new(2, 1)..Point::new(2, 3),
1819                ],
1820                "\n",
1821                cx,
1822            );
1823        });
1824
1825        assert_eq!(
1826            multibuffer.read(cx).snapshot(cx).text(),
1827            concat!(
1828                "\n",     // Preserve newlines
1829                "\n",     //
1830                "bbbb\n", //
1831                "c\n",    //
1832                "cc\n",   //
1833                "\n",     //
1834                "ddd\n",  //
1835                "eeee\n", //
1836                "\n",     //
1837                "\n",     //
1838                "\n",     //
1839                "jj\n"    //
1840            )
1841        );
1842
1843        assert_eq!(
1844            subscription.consume().into_inner(),
1845            [Edit {
1846                old: 8..10,
1847                new: 8..9
1848            }]
1849        );
1850    }
1851
1852    #[gpui::test]
1853    fn test_singleton_multibuffer_anchors(cx: &mut MutableAppContext) {
1854        let buffer = cx.add_model(|cx| Buffer::new(0, "abcd", cx));
1855        let multibuffer = cx.add_model(|cx| MultiBuffer::singleton(buffer.clone(), cx));
1856        let old_snapshot = multibuffer.read(cx).snapshot(cx);
1857        buffer.update(cx, |buffer, cx| {
1858            buffer.edit([0..0], "X", cx);
1859            buffer.edit([5..5], "Y", cx);
1860        });
1861        let new_snapshot = multibuffer.read(cx).snapshot(cx);
1862
1863        assert_eq!(old_snapshot.text(), "abcd");
1864        assert_eq!(new_snapshot.text(), "XabcdY");
1865
1866        assert_eq!(old_snapshot.anchor_before(0).to_offset(&new_snapshot), 0);
1867        assert_eq!(old_snapshot.anchor_after(0).to_offset(&new_snapshot), 1);
1868        assert_eq!(old_snapshot.anchor_before(4).to_offset(&new_snapshot), 5);
1869        assert_eq!(old_snapshot.anchor_after(4).to_offset(&new_snapshot), 6);
1870    }
1871
1872    #[gpui::test]
1873    fn test_multibuffer_anchors(cx: &mut MutableAppContext) {
1874        let buffer_1 = cx.add_model(|cx| Buffer::new(0, "abcd", cx));
1875        let buffer_2 = cx.add_model(|cx| Buffer::new(0, "efghi", cx));
1876        let multibuffer = cx.add_model(|cx| {
1877            let mut multibuffer = MultiBuffer::new(0);
1878            multibuffer.push_excerpt(
1879                ExcerptProperties {
1880                    buffer: &buffer_1,
1881                    range: 0..4,
1882                    header_height: 1,
1883                    render_header: None,
1884                },
1885                cx,
1886            );
1887            multibuffer.push_excerpt(
1888                ExcerptProperties {
1889                    buffer: &buffer_2,
1890                    range: 0..5,
1891                    header_height: 1,
1892                    render_header: None,
1893                },
1894                cx,
1895            );
1896            multibuffer
1897        });
1898        let old_snapshot = multibuffer.read(cx).snapshot(cx);
1899
1900        buffer_1.update(cx, |buffer, cx| {
1901            buffer.edit([0..0], "W", cx);
1902            buffer.edit([5..5], "X", cx);
1903        });
1904        buffer_2.update(cx, |buffer, cx| {
1905            buffer.edit([0..0], "Y", cx);
1906            buffer.edit([6..0], "Z", cx);
1907        });
1908        let new_snapshot = multibuffer.read(cx).snapshot(cx);
1909
1910        assert_eq!(old_snapshot.text(), "\nabcd\n\nefghi\n");
1911        assert_eq!(new_snapshot.text(), "\nWabcdX\n\nYefghiZ\n");
1912
1913        assert_eq!(old_snapshot.anchor_before(0).to_offset(&new_snapshot), 0);
1914        assert_eq!(old_snapshot.anchor_after(0).to_offset(&new_snapshot), 1);
1915        assert_eq!(old_snapshot.anchor_before(1).to_offset(&new_snapshot), 0);
1916        assert_eq!(old_snapshot.anchor_after(1).to_offset(&new_snapshot), 1);
1917        assert_eq!(old_snapshot.anchor_before(7).to_offset(&new_snapshot), 9);
1918        assert_eq!(old_snapshot.anchor_after(7).to_offset(&new_snapshot), 10);
1919    }
1920
1921    #[gpui::test(iterations = 100)]
1922    fn test_random_excerpts(cx: &mut MutableAppContext, mut rng: StdRng) {
1923        let operations = env::var("OPERATIONS")
1924            .map(|i| i.parse().expect("invalid `OPERATIONS` variable"))
1925            .unwrap_or(10);
1926
1927        let mut buffers: Vec<ModelHandle<Buffer>> = Vec::new();
1928        let list = cx.add_model(|_| MultiBuffer::new(0));
1929        let mut excerpt_ids = Vec::new();
1930        let mut expected_excerpts = Vec::new();
1931        let mut old_versions = Vec::new();
1932
1933        for _ in 0..operations {
1934            match rng.gen_range(0..100) {
1935                0..=19 if !buffers.is_empty() => {
1936                    let buffer = buffers.choose(&mut rng).unwrap();
1937                    buffer.update(cx, |buf, cx| buf.randomly_edit(&mut rng, 1, cx));
1938                }
1939                _ => {
1940                    let buffer_handle = if buffers.is_empty() || rng.gen_bool(0.4) {
1941                        let base_text = RandomCharIter::new(&mut rng).take(10).collect::<String>();
1942                        buffers.push(cx.add_model(|cx| Buffer::new(0, base_text, cx)));
1943                        buffers.last().unwrap()
1944                    } else {
1945                        buffers.choose(&mut rng).unwrap()
1946                    };
1947
1948                    let buffer = buffer_handle.read(cx);
1949                    let end_ix = buffer.clip_offset(rng.gen_range(0..=buffer.len()), Bias::Right);
1950                    let start_ix = buffer.clip_offset(rng.gen_range(0..=end_ix), Bias::Left);
1951                    let header_height = rng.gen_range(0..=5);
1952                    let anchor_range = buffer.anchor_before(start_ix)..buffer.anchor_after(end_ix);
1953                    log::info!(
1954                        "Pushing excerpt wih header {}, buffer {}: {:?}[{:?}] = {:?}",
1955                        header_height,
1956                        buffer_handle.id(),
1957                        buffer.text(),
1958                        start_ix..end_ix,
1959                        &buffer.text()[start_ix..end_ix]
1960                    );
1961
1962                    let excerpt_id = list.update(cx, |list, cx| {
1963                        list.push_excerpt(
1964                            ExcerptProperties {
1965                                buffer: &buffer_handle,
1966                                range: start_ix..end_ix,
1967                                header_height,
1968                                render_header: None,
1969                            },
1970                            cx,
1971                        )
1972                    });
1973                    excerpt_ids.push(excerpt_id);
1974                    expected_excerpts.push((buffer_handle.clone(), anchor_range, header_height));
1975                }
1976            }
1977
1978            if rng.gen_bool(0.3) {
1979                list.update(cx, |list, cx| {
1980                    old_versions.push((list.snapshot(cx), list.subscribe()));
1981                })
1982            }
1983
1984            let snapshot = list.read(cx).snapshot(cx);
1985
1986            let mut excerpt_starts = Vec::new();
1987            let mut expected_text = String::new();
1988            for (buffer, range, header_height) in &expected_excerpts {
1989                let buffer = buffer.read(cx);
1990                let buffer_range = range.to_offset(buffer);
1991
1992                for _ in 0..*header_height {
1993                    expected_text.push('\n');
1994                }
1995
1996                excerpt_starts.push(TextSummary::from(expected_text.as_str()));
1997                expected_text.extend(buffer.text_for_range(buffer_range.clone()));
1998                expected_text.push('\n');
1999            }
2000
2001            assert_eq!(snapshot.text(), expected_text);
2002
2003            let mut excerpt_starts = excerpt_starts.into_iter();
2004            for (buffer, range, _) in &expected_excerpts {
2005                let buffer_id = buffer.id();
2006                let buffer = buffer.read(cx);
2007                let buffer_range = range.to_offset(buffer);
2008                let buffer_start_point = buffer.offset_to_point(buffer_range.start);
2009                let buffer_start_point_utf16 =
2010                    buffer.text_summary_for_range::<PointUtf16, _>(0..buffer_range.start);
2011
2012                let excerpt_start = excerpt_starts.next().unwrap();
2013                let mut offset = excerpt_start.bytes;
2014                let mut buffer_offset = buffer_range.start;
2015                let mut point = excerpt_start.lines;
2016                let mut buffer_point = buffer_start_point;
2017                let mut point_utf16 = excerpt_start.lines_utf16;
2018                let mut buffer_point_utf16 = buffer_start_point_utf16;
2019                for byte in buffer.bytes_in_range(buffer_range.clone()).flatten() {
2020                    let left_offset = snapshot.clip_offset(offset, Bias::Left);
2021                    let right_offset = snapshot.clip_offset(offset, Bias::Right);
2022                    let buffer_left_offset = buffer.clip_offset(buffer_offset, Bias::Left);
2023                    let buffer_right_offset = buffer.clip_offset(buffer_offset, Bias::Right);
2024                    assert_eq!(
2025                        left_offset,
2026                        excerpt_start.bytes + (buffer_left_offset - buffer_range.start),
2027                        "clip_offset({:?}, Left). buffer: {:?}, buffer offset: {:?}",
2028                        offset,
2029                        buffer_id,
2030                        buffer_offset,
2031                    );
2032                    assert_eq!(
2033                        right_offset,
2034                        excerpt_start.bytes + (buffer_right_offset - buffer_range.start),
2035                        "clip_offset({:?}, Right). buffer: {:?}, buffer offset: {:?}",
2036                        offset,
2037                        buffer_id,
2038                        buffer_offset,
2039                    );
2040
2041                    let left_point = snapshot.clip_point(point, Bias::Left);
2042                    let right_point = snapshot.clip_point(point, Bias::Right);
2043                    let buffer_left_point = buffer.clip_point(buffer_point, Bias::Left);
2044                    let buffer_right_point = buffer.clip_point(buffer_point, Bias::Right);
2045                    assert_eq!(
2046                        left_point,
2047                        excerpt_start.lines + (buffer_left_point - buffer_start_point),
2048                        "clip_point({:?}, Left). buffer: {:?}, buffer point: {:?}",
2049                        point,
2050                        buffer_id,
2051                        buffer_point,
2052                    );
2053                    assert_eq!(
2054                        right_point,
2055                        excerpt_start.lines + (buffer_right_point - buffer_start_point),
2056                        "clip_point({:?}, Right). buffer: {:?}, buffer point: {:?}",
2057                        point,
2058                        buffer_id,
2059                        buffer_point,
2060                    );
2061
2062                    let left_point_utf16 = snapshot.clip_point_utf16(point_utf16, Bias::Left);
2063                    let right_point_utf16 = snapshot.clip_point_utf16(point_utf16, Bias::Right);
2064                    let buffer_left_point_utf16 =
2065                        buffer.clip_point_utf16(buffer_point_utf16, Bias::Left);
2066                    let buffer_right_point_utf16 =
2067                        buffer.clip_point_utf16(buffer_point_utf16, Bias::Right);
2068                    assert_eq!(
2069                        left_point_utf16,
2070                        excerpt_start.lines_utf16
2071                            + (buffer_left_point_utf16 - buffer_start_point_utf16),
2072                        "clip_point_utf16({:?}, Left). buffer: {:?}, buffer point_utf16: {:?}",
2073                        point_utf16,
2074                        buffer_id,
2075                        buffer_point_utf16,
2076                    );
2077                    assert_eq!(
2078                        right_point_utf16,
2079                        excerpt_start.lines_utf16
2080                            + (buffer_right_point_utf16 - buffer_start_point_utf16),
2081                        "clip_point_utf16({:?}, Right). buffer: {:?}, buffer point_utf16: {:?}",
2082                        point_utf16,
2083                        buffer_id,
2084                        buffer_point_utf16,
2085                    );
2086
2087                    assert_eq!(
2088                        snapshot.point_to_offset(left_point),
2089                        left_offset,
2090                        "point_to_offset({:?})",
2091                        left_point,
2092                    );
2093                    assert_eq!(
2094                        snapshot.offset_to_point(left_offset),
2095                        left_point,
2096                        "offset_to_point({:?})",
2097                        left_offset,
2098                    );
2099
2100                    offset += 1;
2101                    buffer_offset += 1;
2102                    if *byte == b'\n' {
2103                        point += Point::new(1, 0);
2104                        point_utf16 += PointUtf16::new(1, 0);
2105                        buffer_point += Point::new(1, 0);
2106                        buffer_point_utf16 += PointUtf16::new(1, 0);
2107                    } else {
2108                        point += Point::new(0, 1);
2109                        point_utf16 += PointUtf16::new(0, 1);
2110                        buffer_point += Point::new(0, 1);
2111                        buffer_point_utf16 += PointUtf16::new(0, 1);
2112                    }
2113                }
2114            }
2115
2116            for (row, line) in expected_text.split('\n').enumerate() {
2117                assert_eq!(
2118                    snapshot.line_len(row as u32),
2119                    line.len() as u32,
2120                    "line_len({}).",
2121                    row
2122                );
2123            }
2124
2125            for _ in 0..10 {
2126                let end_ix = snapshot.clip_offset(rng.gen_range(0..=snapshot.len()), Bias::Right);
2127                let start_ix = snapshot.clip_offset(rng.gen_range(0..=end_ix), Bias::Left);
2128
2129                assert_eq!(
2130                    snapshot
2131                        .text_for_range(start_ix..end_ix)
2132                        .collect::<String>(),
2133                    &expected_text[start_ix..end_ix],
2134                    "incorrect text for range {:?}",
2135                    start_ix..end_ix
2136                );
2137
2138                let expected_summary = TextSummary::from(&expected_text[start_ix..end_ix]);
2139                assert_eq!(
2140                    snapshot.text_summary_for_range::<TextSummary, _>(start_ix..end_ix),
2141                    expected_summary,
2142                    "incorrect summary for range {:?}",
2143                    start_ix..end_ix
2144                );
2145            }
2146        }
2147
2148        let snapshot = list.read(cx).snapshot(cx);
2149        for (old_snapshot, subscription) in old_versions {
2150            let edits = subscription.consume().into_inner();
2151
2152            log::info!(
2153                "applying edits since old text: {:?}: {:?}",
2154                old_snapshot.text(),
2155                edits,
2156            );
2157
2158            let mut text = old_snapshot.text();
2159            for edit in edits {
2160                let new_text: String = snapshot.text_for_range(edit.new.clone()).collect();
2161                text.replace_range(edit.new.start..edit.new.start + edit.old.len(), &new_text);
2162            }
2163            assert_eq!(text.to_string(), snapshot.text());
2164        }
2165    }
2166
2167    #[gpui::test]
2168    fn test_history(cx: &mut MutableAppContext) {
2169        let buffer_1 = cx.add_model(|cx| Buffer::new(0, "1234", cx));
2170        let buffer_2 = cx.add_model(|cx| Buffer::new(0, "5678", cx));
2171        let multibuffer = cx.add_model(|_| MultiBuffer::new(0));
2172        let group_interval = multibuffer.read(cx).history.group_interval;
2173        multibuffer.update(cx, |multibuffer, cx| {
2174            multibuffer.push_excerpt(
2175                ExcerptProperties {
2176                    buffer: &buffer_1,
2177                    range: 0..buffer_1.read(cx).len(),
2178                    header_height: 0,
2179                    render_header: None,
2180                },
2181                cx,
2182            );
2183            multibuffer.push_excerpt(
2184                ExcerptProperties {
2185                    buffer: &buffer_2,
2186                    range: 0..buffer_2.read(cx).len(),
2187                    header_height: 0,
2188                    render_header: None,
2189                },
2190                cx,
2191            );
2192        });
2193
2194        let mut now = Instant::now();
2195
2196        multibuffer.update(cx, |multibuffer, cx| {
2197            multibuffer.start_transaction_at(now, cx);
2198            multibuffer.edit(
2199                [
2200                    Point::new(0, 0)..Point::new(0, 0),
2201                    Point::new(1, 0)..Point::new(1, 0),
2202                ],
2203                "A",
2204                cx,
2205            );
2206            multibuffer.edit(
2207                [
2208                    Point::new(0, 1)..Point::new(0, 1),
2209                    Point::new(1, 1)..Point::new(1, 1),
2210                ],
2211                "B",
2212                cx,
2213            );
2214            multibuffer.end_transaction_at(now, cx);
2215            assert_eq!(multibuffer.read(cx).text(), "AB1234\nAB5678\n");
2216
2217            now += 2 * group_interval;
2218            multibuffer.start_transaction_at(now, cx);
2219            multibuffer.edit([2..2], "C", cx);
2220            multibuffer.end_transaction_at(now, cx);
2221            assert_eq!(multibuffer.read(cx).text(), "ABC1234\nAB5678\n");
2222
2223            multibuffer.undo(cx);
2224            assert_eq!(multibuffer.read(cx).text(), "AB1234\nAB5678\n");
2225
2226            multibuffer.undo(cx);
2227            assert_eq!(multibuffer.read(cx).text(), "1234\n5678\n");
2228
2229            multibuffer.redo(cx);
2230            assert_eq!(multibuffer.read(cx).text(), "AB1234\nAB5678\n");
2231
2232            multibuffer.redo(cx);
2233            assert_eq!(multibuffer.read(cx).text(), "ABC1234\nAB5678\n");
2234
2235            buffer_1.update(cx, |buffer_1, cx| buffer_1.undo(cx));
2236            assert_eq!(multibuffer.read(cx).text(), "AB1234\nAB5678\n");
2237
2238            multibuffer.undo(cx);
2239            assert_eq!(multibuffer.read(cx).text(), "1234\n5678\n");
2240
2241            multibuffer.redo(cx);
2242            assert_eq!(multibuffer.read(cx).text(), "AB1234\nAB5678\n");
2243
2244            multibuffer.redo(cx);
2245            assert_eq!(multibuffer.read(cx).text(), "ABC1234\nAB5678\n");
2246
2247            multibuffer.undo(cx);
2248            assert_eq!(multibuffer.read(cx).text(), "AB1234\nAB5678\n");
2249
2250            buffer_1.update(cx, |buffer_1, cx| buffer_1.redo(cx));
2251            assert_eq!(multibuffer.read(cx).text(), "ABC1234\nAB5678\n");
2252
2253            multibuffer.undo(cx);
2254            assert_eq!(multibuffer.read(cx).text(), "C1234\n5678\n");
2255        });
2256    }
2257}