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        id
 563    }
 564
 565    fn on_buffer_event(
 566        &mut self,
 567        _: ModelHandle<Buffer>,
 568        event: &Event,
 569        cx: &mut ModelContext<Self>,
 570    ) {
 571        cx.emit(event.clone());
 572    }
 573
 574    pub fn save(
 575        &mut self,
 576        cx: &mut ModelContext<Self>,
 577    ) -> Result<Task<Result<(clock::Global, SystemTime)>>> {
 578        self.as_singleton()
 579            .unwrap()
 580            .update(cx, |buffer, cx| buffer.save(cx))
 581    }
 582
 583    pub fn language<'a>(&self, cx: &'a AppContext) -> Option<&'a Arc<Language>> {
 584        self.buffers
 585            .values()
 586            .next()
 587            .and_then(|state| state.buffer.read(cx).language())
 588    }
 589
 590    pub fn file<'a>(&self, cx: &'a AppContext) -> Option<&'a dyn File> {
 591        self.as_singleton().unwrap().read(cx).file()
 592    }
 593
 594    pub fn is_dirty(&self, cx: &AppContext) -> bool {
 595        self.as_singleton().unwrap().read(cx).is_dirty()
 596    }
 597
 598    pub fn has_conflict(&self, cx: &AppContext) -> bool {
 599        self.as_singleton().unwrap().read(cx).has_conflict()
 600    }
 601
 602    pub fn is_parsing(&self, cx: &AppContext) -> bool {
 603        self.as_singleton().unwrap().read(cx).is_parsing()
 604    }
 605
 606    fn sync(&self, cx: &AppContext) {
 607        let mut snapshot = self.snapshot.borrow_mut();
 608        let mut excerpts_to_edit = Vec::new();
 609        let mut reparsed = false;
 610        let mut diagnostics_updated = false;
 611        for buffer_state in self.buffers.values() {
 612            let buffer = buffer_state.buffer.read(cx);
 613            let buffer_edited = buffer.version().gt(&buffer_state.last_version);
 614            let buffer_reparsed = buffer.parse_count() > buffer_state.last_parse_count;
 615            let buffer_diagnostics_updated =
 616                buffer.diagnostics_update_count() > buffer_state.last_diagnostics_update_count;
 617            if buffer_edited || buffer_reparsed || buffer_diagnostics_updated {
 618                excerpts_to_edit.extend(
 619                    buffer_state
 620                        .excerpts
 621                        .iter()
 622                        .map(|excerpt_id| (excerpt_id, buffer_state, buffer_edited)),
 623                );
 624            }
 625
 626            reparsed |= buffer_reparsed;
 627            diagnostics_updated |= buffer_diagnostics_updated;
 628        }
 629        if reparsed {
 630            snapshot.parse_count += 1;
 631        }
 632        if diagnostics_updated {
 633            snapshot.diagnostics_update_count += 1;
 634        }
 635        excerpts_to_edit.sort_unstable_by_key(|(excerpt_id, _, _)| *excerpt_id);
 636
 637        let mut edits = Vec::new();
 638        let mut new_excerpts = SumTree::new();
 639        let mut cursor = snapshot.excerpts.cursor::<(Option<&ExcerptId>, usize)>();
 640
 641        for (id, buffer_state, buffer_edited) in excerpts_to_edit {
 642            new_excerpts.push_tree(cursor.slice(&Some(id), Bias::Left, &()), &());
 643            let old_excerpt = cursor.item().unwrap();
 644            let buffer = buffer_state.buffer.read(cx);
 645
 646            let mut new_excerpt;
 647            if buffer_edited {
 648                edits.extend(
 649                    buffer
 650                        .edits_since_in_range::<usize>(
 651                            old_excerpt.buffer.version(),
 652                            old_excerpt.range.clone(),
 653                        )
 654                        .map(|mut edit| {
 655                            let excerpt_old_start =
 656                                cursor.start().1 + old_excerpt.header_height as usize;
 657                            let excerpt_new_start = new_excerpts.summary().text.bytes
 658                                + old_excerpt.header_height as usize;
 659                            edit.old.start += excerpt_old_start;
 660                            edit.old.end += excerpt_old_start;
 661                            edit.new.start += excerpt_new_start;
 662                            edit.new.end += excerpt_new_start;
 663                            edit
 664                        }),
 665                );
 666
 667                new_excerpt = Excerpt::new(
 668                    id.clone(),
 669                    buffer_state.buffer.id(),
 670                    buffer.snapshot(),
 671                    old_excerpt.range.clone(),
 672                    old_excerpt.header_height,
 673                    old_excerpt.render_header.clone(),
 674                    !self.singleton,
 675                );
 676            } else {
 677                new_excerpt = old_excerpt.clone();
 678                new_excerpt.buffer = buffer.snapshot();
 679            }
 680
 681            new_excerpts.push(new_excerpt, &());
 682            cursor.next(&());
 683        }
 684        new_excerpts.push_tree(cursor.suffix(&()), &());
 685
 686        drop(cursor);
 687        snapshot.excerpts = new_excerpts;
 688
 689        self.subscriptions.publish(edits);
 690    }
 691}
 692
 693#[cfg(any(test, feature = "test-support"))]
 694impl MultiBuffer {
 695    pub fn randomly_edit<R: rand::Rng>(
 696        &mut self,
 697        rng: &mut R,
 698        count: usize,
 699        cx: &mut ModelContext<Self>,
 700    ) {
 701        self.as_singleton()
 702            .unwrap()
 703            .update(cx, |buffer, cx| buffer.randomly_edit(rng, count, cx));
 704        self.sync(cx);
 705    }
 706}
 707
 708impl Entity for MultiBuffer {
 709    type Event = language::Event;
 710}
 711
 712impl MultiBufferSnapshot {
 713    pub fn text(&self) -> String {
 714        self.chunks(0..self.len(), None)
 715            .map(|chunk| chunk.text)
 716            .collect()
 717    }
 718
 719    pub fn excerpt_headers_in_range<'a>(
 720        &'a self,
 721        range: Range<u32>,
 722    ) -> impl 'a + Iterator<Item = (Range<u32>, RenderHeaderFn)> {
 723        let mut cursor = self.excerpts.cursor::<Point>();
 724        cursor.seek(&Point::new(range.start, 0), Bias::Right, &());
 725
 726        if let Some(excerpt) = cursor.item() {
 727            if range.start >= cursor.start().row + excerpt.header_height as u32 {
 728                cursor.next(&());
 729            }
 730        }
 731
 732        iter::from_fn(move || {
 733            while let Some(excerpt) = cursor.item() {
 734                if cursor.start().row >= range.end {
 735                    break;
 736                }
 737
 738                if let Some(render) = excerpt.render_header.clone() {
 739                    let start = cursor.start().row;
 740                    let end = start + excerpt.header_height as u32;
 741                    cursor.next(&());
 742                    return Some((start..end, render));
 743                } else {
 744                    cursor.next(&());
 745                }
 746            }
 747            None
 748        })
 749    }
 750
 751    pub fn reversed_chars_at<'a, T: ToOffset>(
 752        &'a self,
 753        position: T,
 754    ) -> impl Iterator<Item = char> + 'a {
 755        // TODO
 756        let offset = position.to_offset(self);
 757        self.as_singleton().unwrap().reversed_chars_at(offset)
 758    }
 759
 760    pub fn chars_at<'a, T: ToOffset>(&'a self, position: T) -> impl Iterator<Item = char> + 'a {
 761        let offset = position.to_offset(self);
 762        self.text_for_range(offset..self.len())
 763            .flat_map(|chunk| chunk.chars())
 764    }
 765
 766    pub fn text_for_range<'a, T: ToOffset>(
 767        &'a self,
 768        range: Range<T>,
 769    ) -> impl Iterator<Item = &'a str> {
 770        self.chunks(range, None).map(|chunk| chunk.text)
 771    }
 772
 773    pub fn is_line_blank(&self, row: u32) -> bool {
 774        self.text_for_range(Point::new(row, 0)..Point::new(row, self.line_len(row)))
 775            .all(|chunk| chunk.matches(|c: char| !c.is_whitespace()).next().is_none())
 776    }
 777
 778    pub fn contains_str_at<T>(&self, position: T, needle: &str) -> bool
 779    where
 780        T: ToOffset,
 781    {
 782        let position = position.to_offset(self);
 783        position == self.clip_offset(position, Bias::Left)
 784            && self
 785                .bytes_in_range(position..self.len())
 786                .flatten()
 787                .copied()
 788                .take(needle.len())
 789                .eq(needle.bytes())
 790    }
 791
 792    fn as_singleton(&self) -> Option<&BufferSnapshot> {
 793        let mut excerpts = self.excerpts.iter();
 794        let buffer = excerpts.next().map(|excerpt| &excerpt.buffer);
 795        if excerpts.next().is_none() {
 796            buffer
 797        } else {
 798            None
 799        }
 800    }
 801
 802    pub fn len(&self) -> usize {
 803        self.excerpts.summary().text.bytes
 804    }
 805
 806    pub fn clip_offset(&self, offset: usize, bias: Bias) -> usize {
 807        let mut cursor = self.excerpts.cursor::<usize>();
 808        cursor.seek(&offset, Bias::Right, &());
 809        if let Some(excerpt) = cursor.item() {
 810            let start_after_header = *cursor.start() + excerpt.header_height as usize;
 811            if offset < start_after_header {
 812                *cursor.start()
 813            } else {
 814                let excerpt_start = excerpt.range.start.to_offset(&excerpt.buffer);
 815                let buffer_offset = excerpt
 816                    .buffer
 817                    .clip_offset(excerpt_start + (offset - start_after_header), bias);
 818                let offset_in_excerpt = if buffer_offset > excerpt_start {
 819                    buffer_offset - excerpt_start
 820                } else {
 821                    0
 822                };
 823                start_after_header + offset_in_excerpt
 824            }
 825        } else {
 826            self.excerpts.summary().text.bytes
 827        }
 828    }
 829
 830    pub fn clip_point(&self, point: Point, bias: Bias) -> Point {
 831        let mut cursor = self.excerpts.cursor::<Point>();
 832        cursor.seek(&point, Bias::Right, &());
 833        if let Some(excerpt) = cursor.item() {
 834            let start_after_header = *cursor.start() + Point::new(excerpt.header_height as u32, 0);
 835            if point < start_after_header {
 836                *cursor.start()
 837            } else {
 838                let excerpt_start = excerpt.range.start.to_point(&excerpt.buffer);
 839                let buffer_point = excerpt
 840                    .buffer
 841                    .clip_point(excerpt_start + (point - start_after_header), bias);
 842                let point_in_excerpt = if buffer_point > excerpt_start {
 843                    buffer_point - excerpt_start
 844                } else {
 845                    Point::zero()
 846                };
 847                start_after_header + point_in_excerpt
 848            }
 849        } else {
 850            self.excerpts.summary().text.lines
 851        }
 852    }
 853
 854    pub fn clip_point_utf16(&self, point: PointUtf16, bias: Bias) -> PointUtf16 {
 855        let mut cursor = self.excerpts.cursor::<PointUtf16>();
 856        cursor.seek(&point, Bias::Right, &());
 857        if let Some(excerpt) = cursor.item() {
 858            let start_after_header =
 859                *cursor.start() + PointUtf16::new(excerpt.header_height as u32, 0);
 860            if point < start_after_header {
 861                *cursor.start()
 862            } else {
 863                let excerpt_start = excerpt
 864                    .buffer
 865                    .offset_to_point_utf16(excerpt.range.start.to_offset(&excerpt.buffer));
 866                let buffer_point = excerpt
 867                    .buffer
 868                    .clip_point_utf16(excerpt_start + (point - start_after_header), bias);
 869                let point_in_excerpt = if buffer_point > excerpt_start {
 870                    buffer_point - excerpt_start
 871                } else {
 872                    PointUtf16::new(0, 0)
 873                };
 874                start_after_header + point_in_excerpt
 875            }
 876        } else {
 877            self.excerpts.summary().text.lines_utf16
 878        }
 879    }
 880
 881    pub fn bytes_in_range<'a, T: ToOffset>(&'a self, range: Range<T>) -> MultiBufferBytes<'a> {
 882        MultiBufferBytes {
 883            chunks: self.chunks(range, None).peekable(),
 884        }
 885    }
 886
 887    pub fn chunks<'a, T: ToOffset>(
 888        &'a self,
 889        range: Range<T>,
 890        theme: Option<&'a SyntaxTheme>,
 891    ) -> MultiBufferChunks<'a> {
 892        let mut result = MultiBufferChunks {
 893            range: 0..range.end.to_offset(self),
 894            cursor: self.excerpts.cursor::<usize>(),
 895            header_height: 0,
 896            excerpt_chunks: None,
 897            has_trailing_newline: false,
 898            theme,
 899        };
 900        result.seek(range.start.to_offset(self));
 901        result
 902    }
 903
 904    pub fn offset_to_point(&self, offset: usize) -> Point {
 905        let mut cursor = self.excerpts.cursor::<(usize, Point)>();
 906        cursor.seek(&offset, Bias::Right, &());
 907        if let Some(excerpt) = cursor.item() {
 908            let (start_offset, start_point) = cursor.start();
 909            let overshoot = offset - start_offset;
 910            let header_height = excerpt.header_height as usize;
 911            if overshoot < header_height {
 912                *start_point
 913            } else {
 914                let excerpt_start_offset = excerpt.range.start.to_offset(&excerpt.buffer);
 915                let excerpt_start_point = excerpt.range.start.to_point(&excerpt.buffer);
 916                let buffer_point = excerpt
 917                    .buffer
 918                    .offset_to_point(excerpt_start_offset + (overshoot - header_height));
 919                *start_point
 920                    + Point::new(header_height as u32, 0)
 921                    + (buffer_point - excerpt_start_point)
 922            }
 923        } else {
 924            self.excerpts.summary().text.lines
 925        }
 926    }
 927
 928    pub fn point_to_offset(&self, point: Point) -> usize {
 929        let mut cursor = self.excerpts.cursor::<(Point, usize)>();
 930        cursor.seek(&point, Bias::Right, &());
 931        if let Some(excerpt) = cursor.item() {
 932            let (start_point, start_offset) = cursor.start();
 933            let overshoot = point - start_point;
 934            let header_height = Point::new(excerpt.header_height as u32, 0);
 935            if overshoot < header_height {
 936                *start_offset
 937            } else {
 938                let excerpt_start_offset = excerpt.range.start.to_offset(&excerpt.buffer);
 939                let excerpt_start_point = excerpt.range.start.to_point(&excerpt.buffer);
 940                let buffer_offset = excerpt
 941                    .buffer
 942                    .point_to_offset(excerpt_start_point + (overshoot - header_height));
 943                *start_offset + excerpt.header_height as usize + buffer_offset
 944                    - excerpt_start_offset
 945            }
 946        } else {
 947            self.excerpts.summary().text.bytes
 948        }
 949    }
 950
 951    pub fn point_utf16_to_offset(&self, point: PointUtf16) -> usize {
 952        let mut cursor = self.excerpts.cursor::<(PointUtf16, usize)>();
 953        cursor.seek(&point, Bias::Right, &());
 954        if let Some(excerpt) = cursor.item() {
 955            let (start_point, start_offset) = cursor.start();
 956            let overshoot = point - start_point;
 957            let header_height = PointUtf16::new(excerpt.header_height as u32, 0);
 958            if overshoot < header_height {
 959                *start_offset
 960            } else {
 961                let excerpt_start_offset = excerpt.range.start.to_offset(&excerpt.buffer);
 962                let excerpt_start_point = excerpt
 963                    .buffer
 964                    .offset_to_point_utf16(excerpt.range.start.to_offset(&excerpt.buffer));
 965                let buffer_offset = excerpt
 966                    .buffer
 967                    .point_utf16_to_offset(excerpt_start_point + (overshoot - header_height));
 968                *start_offset
 969                    + excerpt.header_height as usize
 970                    + (buffer_offset - excerpt_start_offset)
 971            }
 972        } else {
 973            self.excerpts.summary().text.bytes
 974        }
 975    }
 976
 977    pub fn indent_column_for_line(&self, row: u32) -> u32 {
 978        if let Some((buffer, range)) = self.buffer_line_for_row(row) {
 979            buffer
 980                .indent_column_for_line(range.start.row)
 981                .min(range.end.column)
 982                .saturating_sub(range.start.column)
 983        } else {
 984            0
 985        }
 986    }
 987
 988    pub fn line_len(&self, row: u32) -> u32 {
 989        if let Some((_, range)) = self.buffer_line_for_row(row) {
 990            range.end.column - range.start.column
 991        } else {
 992            0
 993        }
 994    }
 995
 996    fn buffer_line_for_row(&self, row: u32) -> Option<(&BufferSnapshot, Range<Point>)> {
 997        let mut cursor = self.excerpts.cursor::<Point>();
 998        cursor.seek(&Point::new(row, 0), Bias::Right, &());
 999        if let Some(excerpt) = cursor.item() {
1000            let overshoot = row - cursor.start().row;
1001            let header_height = excerpt.header_height as u32;
1002            if overshoot >= header_height {
1003                let excerpt_start = excerpt.range.start.to_point(&excerpt.buffer);
1004                let excerpt_end = excerpt.range.end.to_point(&excerpt.buffer);
1005                let buffer_row = excerpt_start.row + overshoot - header_height;
1006                let line_start = Point::new(buffer_row, 0);
1007                let line_end = Point::new(buffer_row, excerpt.buffer.line_len(buffer_row));
1008                return Some((
1009                    &excerpt.buffer,
1010                    line_start.max(excerpt_start)..line_end.min(excerpt_end),
1011                ));
1012            }
1013        }
1014        None
1015    }
1016
1017    pub fn max_point(&self) -> Point {
1018        self.text_summary().lines
1019    }
1020
1021    pub fn text_summary(&self) -> TextSummary {
1022        self.excerpts.summary().text
1023    }
1024
1025    pub fn text_summary_for_range<'a, D, O>(&'a self, range: Range<O>) -> D
1026    where
1027        D: TextDimension,
1028        O: ToOffset,
1029    {
1030        let mut summary = D::default();
1031        let mut range = range.start.to_offset(self)..range.end.to_offset(self);
1032        let mut cursor = self.excerpts.cursor::<usize>();
1033        cursor.seek(&range.start, Bias::Right, &());
1034        if let Some(excerpt) = cursor.item() {
1035            let start_after_header = cursor.start() + excerpt.header_height as usize;
1036            if range.start < start_after_header {
1037                let header_len = cmp::min(range.end, start_after_header) - range.start;
1038                summary.add_assign(&D::from_text_summary(&TextSummary {
1039                    bytes: header_len,
1040                    lines: Point::new(header_len as u32, 0),
1041                    lines_utf16: PointUtf16::new(header_len as u32, 0),
1042                    first_line_chars: 0,
1043                    last_line_chars: 0,
1044                    longest_row: 0,
1045                    longest_row_chars: 0,
1046                }));
1047                range.start = start_after_header;
1048                range.end = cmp::max(range.start, range.end);
1049            }
1050
1051            let mut end_before_newline = cursor.end(&());
1052            if excerpt.has_trailing_newline {
1053                end_before_newline -= 1;
1054            }
1055
1056            let excerpt_start = excerpt.range.start.to_offset(&excerpt.buffer);
1057            let start_in_excerpt = excerpt_start + (range.start - start_after_header);
1058            let end_in_excerpt =
1059                excerpt_start + (cmp::min(end_before_newline, range.end) - start_after_header);
1060            summary.add_assign(
1061                &excerpt
1062                    .buffer
1063                    .text_summary_for_range(start_in_excerpt..end_in_excerpt),
1064            );
1065
1066            if range.end > end_before_newline {
1067                summary.add_assign(&D::from_text_summary(&TextSummary {
1068                    bytes: 1,
1069                    lines: Point::new(1 as u32, 0),
1070                    lines_utf16: PointUtf16::new(1 as u32, 0),
1071                    first_line_chars: 0,
1072                    last_line_chars: 0,
1073                    longest_row: 0,
1074                    longest_row_chars: 0,
1075                }));
1076            }
1077
1078            cursor.next(&());
1079        }
1080
1081        if range.end > *cursor.start() {
1082            summary.add_assign(&D::from_text_summary(&cursor.summary::<_, TextSummary>(
1083                &range.end,
1084                Bias::Right,
1085                &(),
1086            )));
1087            if let Some(excerpt) = cursor.item() {
1088                let start_after_header = cursor.start() + excerpt.header_height as usize;
1089                let header_len =
1090                    cmp::min(range.end - cursor.start(), excerpt.header_height as usize);
1091                summary.add_assign(&D::from_text_summary(&TextSummary {
1092                    bytes: header_len,
1093                    lines: Point::new(header_len as u32, 0),
1094                    lines_utf16: PointUtf16::new(header_len as u32, 0),
1095                    first_line_chars: 0,
1096                    last_line_chars: 0,
1097                    longest_row: 0,
1098                    longest_row_chars: 0,
1099                }));
1100                range.end = cmp::max(start_after_header, range.end);
1101
1102                let excerpt_start = excerpt.range.start.to_offset(&excerpt.buffer);
1103                let end_in_excerpt = excerpt_start + (range.end - start_after_header);
1104                summary.add_assign(
1105                    &excerpt
1106                        .buffer
1107                        .text_summary_for_range(excerpt_start..end_in_excerpt),
1108                );
1109                cursor.next(&());
1110            }
1111        }
1112
1113        summary
1114    }
1115
1116    pub fn summary_for_anchor<D>(&self, anchor: &Anchor) -> D
1117    where
1118        D: TextDimension + Ord + Sub<D, Output = D>,
1119    {
1120        let mut cursor = self.excerpts.cursor::<ExcerptSummary>();
1121        cursor.seek(&Some(&anchor.excerpt_id), Bias::Left, &());
1122        if let Some(excerpt) = cursor.item() {
1123            if excerpt.id == anchor.excerpt_id {
1124                let mut excerpt_start = D::from_text_summary(&cursor.start().text);
1125                excerpt_start.add_summary(&excerpt.header_summary(), &());
1126                let excerpt_buffer_start = excerpt.range.start.summary::<D>(&excerpt.buffer);
1127                let buffer_point = anchor.text_anchor.summary::<D>(&excerpt.buffer);
1128                if buffer_point > excerpt_buffer_start {
1129                    excerpt_start.add_assign(&(buffer_point - excerpt_buffer_start));
1130                }
1131                return excerpt_start;
1132            }
1133        }
1134        D::from_text_summary(&cursor.start().text)
1135    }
1136
1137    pub fn summaries_for_anchors<'a, D, I>(&'a self, anchors: I) -> Vec<D>
1138    where
1139        D: TextDimension + Ord + Sub<D, Output = D>,
1140        I: 'a + IntoIterator<Item = &'a Anchor>,
1141    {
1142        let mut anchors = anchors.into_iter().peekable();
1143        let mut cursor = self.excerpts.cursor::<ExcerptSummary>();
1144        let mut summaries = Vec::new();
1145        while let Some(anchor) = anchors.peek() {
1146            let excerpt_id = &anchor.excerpt_id;
1147            let excerpt_anchors = iter::from_fn(|| {
1148                let anchor = anchors.peek()?;
1149                if anchor.excerpt_id == *excerpt_id {
1150                    Some(&anchors.next().unwrap().text_anchor)
1151                } else {
1152                    None
1153                }
1154            });
1155
1156            cursor.seek_forward(&Some(excerpt_id), Bias::Left, &());
1157            if let Some(excerpt) = cursor.item() {
1158                if excerpt.id == *excerpt_id {
1159                    let mut excerpt_start = D::from_text_summary(&cursor.start().text);
1160                    excerpt_start.add_summary(&excerpt.header_summary(), &());
1161                    let excerpt_buffer_start = excerpt.range.start.summary::<D>(&excerpt.buffer);
1162                    summaries.extend(
1163                        excerpt
1164                            .buffer
1165                            .summaries_for_anchors::<D, _>(excerpt_anchors)
1166                            .map(move |summary| {
1167                                let mut excerpt_start = excerpt_start.clone();
1168                                let excerpt_buffer_start = excerpt_buffer_start.clone();
1169                                if summary > excerpt_buffer_start {
1170                                    excerpt_start.add_assign(&(summary - excerpt_buffer_start));
1171                                }
1172                                excerpt_start
1173                            }),
1174                    );
1175                    continue;
1176                }
1177            }
1178
1179            let summary = D::from_text_summary(&cursor.start().text);
1180            summaries.extend(excerpt_anchors.map(|_| summary.clone()));
1181        }
1182
1183        summaries
1184    }
1185
1186    pub fn anchor_before<T: ToOffset>(&self, position: T) -> Anchor {
1187        self.anchor_at(position, Bias::Left)
1188    }
1189
1190    pub fn anchor_after<T: ToOffset>(&self, position: T) -> Anchor {
1191        self.anchor_at(position, Bias::Right)
1192    }
1193
1194    pub fn anchor_at<T: ToOffset>(&self, position: T, bias: Bias) -> Anchor {
1195        let offset = position.to_offset(self);
1196        let mut cursor = self.excerpts.cursor::<(usize, Option<&ExcerptId>)>();
1197        cursor.seek(&offset, Bias::Right, &());
1198        if cursor.item().is_none() && offset == cursor.start().0 && bias == Bias::Left {
1199            cursor.prev(&());
1200        }
1201        if let Some(excerpt) = cursor.item() {
1202            let start_after_header = cursor.start().0 + excerpt.header_height as usize;
1203            let buffer_start = excerpt.range.start.to_offset(&excerpt.buffer);
1204            let overshoot = offset.saturating_sub(start_after_header);
1205            Anchor {
1206                excerpt_id: excerpt.id.clone(),
1207                text_anchor: excerpt.buffer.anchor_at(buffer_start + overshoot, bias),
1208            }
1209        } else if offset == 0 && bias == Bias::Left {
1210            Anchor::min()
1211        } else {
1212            Anchor::max()
1213        }
1214    }
1215
1216    pub fn parse_count(&self) -> usize {
1217        self.parse_count
1218    }
1219
1220    pub fn enclosing_bracket_ranges<T: ToOffset>(
1221        &self,
1222        range: Range<T>,
1223    ) -> Option<(Range<usize>, Range<usize>)> {
1224        let range = range.start.to_offset(self)..range.end.to_offset(self);
1225        self.as_singleton().unwrap().enclosing_bracket_ranges(range)
1226    }
1227
1228    pub fn diagnostics_update_count(&self) -> usize {
1229        self.diagnostics_update_count
1230    }
1231
1232    pub fn language(&self) -> Option<&Arc<Language>> {
1233        self.excerpts
1234            .iter()
1235            .next()
1236            .and_then(|excerpt| excerpt.buffer.language())
1237    }
1238
1239    pub fn diagnostic_group<'a, O>(
1240        &'a self,
1241        group_id: usize,
1242    ) -> impl Iterator<Item = DiagnosticEntry<O>> + 'a
1243    where
1244        O: text::FromAnchor + 'a,
1245    {
1246        self.as_singleton().unwrap().diagnostic_group(group_id)
1247    }
1248
1249    pub fn diagnostics_in_range<'a, T, O>(
1250        &'a self,
1251        range: Range<T>,
1252    ) -> impl Iterator<Item = DiagnosticEntry<O>> + 'a
1253    where
1254        T: 'a + ToOffset,
1255        O: 'a + text::FromAnchor,
1256    {
1257        let range = range.start.to_offset(self)..range.end.to_offset(self);
1258        self.as_singleton().unwrap().diagnostics_in_range(range)
1259    }
1260
1261    pub fn range_for_syntax_ancestor<T: ToOffset>(&self, range: Range<T>) -> Option<Range<usize>> {
1262        let range = range.start.to_offset(self)..range.end.to_offset(self);
1263        self.as_singleton()
1264            .unwrap()
1265            .range_for_syntax_ancestor(range)
1266    }
1267
1268    fn buffer_snapshot_for_excerpt<'a>(
1269        &'a self,
1270        excerpt_id: &'a ExcerptId,
1271    ) -> Option<&'a BufferSnapshot> {
1272        let mut cursor = self.excerpts.cursor::<Option<&ExcerptId>>();
1273        cursor.seek(&Some(excerpt_id), Bias::Left, &());
1274        if let Some(excerpt) = cursor.item() {
1275            if excerpt.id == *excerpt_id {
1276                return Some(&excerpt.buffer);
1277            }
1278        }
1279        None
1280    }
1281
1282    pub fn remote_selections_in_range<'a>(
1283        &'a self,
1284        range: &'a Range<Anchor>,
1285    ) -> impl 'a + Iterator<Item = (ReplicaId, Selection<Anchor>)> {
1286        let mut cursor = self.excerpts.cursor::<Option<&ExcerptId>>();
1287        cursor.seek(&Some(&range.start.excerpt_id), Bias::Left, &());
1288        cursor
1289            .take_while(move |excerpt| excerpt.id <= range.end.excerpt_id)
1290            .flat_map(move |excerpt| {
1291                let mut query_range = excerpt.range.start.clone()..excerpt.range.end.clone();
1292                if excerpt.id == range.start.excerpt_id {
1293                    query_range.start = range.start.text_anchor.clone();
1294                }
1295                if excerpt.id == range.end.excerpt_id {
1296                    query_range.end = range.end.text_anchor.clone();
1297                }
1298
1299                excerpt
1300                    .buffer
1301                    .remote_selections_in_range(query_range)
1302                    .flat_map(move |(replica_id, selections)| {
1303                        selections.map(move |selection| {
1304                            let mut start = Anchor {
1305                                excerpt_id: excerpt.id.clone(),
1306                                text_anchor: selection.start.clone(),
1307                            };
1308                            let mut end = Anchor {
1309                                excerpt_id: excerpt.id.clone(),
1310                                text_anchor: selection.end.clone(),
1311                            };
1312                            if range.start.cmp(&start, self).unwrap().is_gt() {
1313                                start = range.start.clone();
1314                            }
1315                            if range.end.cmp(&end, self).unwrap().is_lt() {
1316                                end = range.end.clone();
1317                            }
1318
1319                            (
1320                                replica_id,
1321                                Selection {
1322                                    id: selection.id,
1323                                    start,
1324                                    end,
1325                                    reversed: selection.reversed,
1326                                    goal: selection.goal,
1327                                },
1328                            )
1329                        })
1330                    })
1331            })
1332    }
1333}
1334
1335impl History {
1336    fn start_transaction(&mut self, now: Instant) -> Option<TransactionId> {
1337        self.transaction_depth += 1;
1338        if self.transaction_depth == 1 {
1339            let id = post_inc(&mut self.next_transaction_id);
1340            self.undo_stack.push(Transaction {
1341                id,
1342                buffer_transactions: Default::default(),
1343                first_edit_at: now,
1344                last_edit_at: now,
1345            });
1346            Some(id)
1347        } else {
1348            None
1349        }
1350    }
1351
1352    fn end_transaction(
1353        &mut self,
1354        now: Instant,
1355        buffer_transactions: HashSet<(usize, TransactionId)>,
1356    ) -> bool {
1357        assert_ne!(self.transaction_depth, 0);
1358        self.transaction_depth -= 1;
1359        if self.transaction_depth == 0 {
1360            if buffer_transactions.is_empty() {
1361                self.undo_stack.pop();
1362                false
1363            } else {
1364                let transaction = self.undo_stack.last_mut().unwrap();
1365                transaction.last_edit_at = now;
1366                transaction.buffer_transactions.extend(buffer_transactions);
1367                true
1368            }
1369        } else {
1370            false
1371        }
1372    }
1373
1374    fn pop_undo(&mut self) -> Option<&Transaction> {
1375        assert_eq!(self.transaction_depth, 0);
1376        if let Some(transaction) = self.undo_stack.pop() {
1377            self.redo_stack.push(transaction);
1378            self.redo_stack.last()
1379        } else {
1380            None
1381        }
1382    }
1383
1384    fn pop_redo(&mut self) -> Option<&Transaction> {
1385        assert_eq!(self.transaction_depth, 0);
1386        if let Some(transaction) = self.redo_stack.pop() {
1387            self.undo_stack.push(transaction);
1388            self.undo_stack.last()
1389        } else {
1390            None
1391        }
1392    }
1393
1394    fn group(&mut self) -> Option<TransactionId> {
1395        let mut new_len = self.undo_stack.len();
1396        let mut transactions = self.undo_stack.iter_mut();
1397
1398        if let Some(mut transaction) = transactions.next_back() {
1399            while let Some(prev_transaction) = transactions.next_back() {
1400                if transaction.first_edit_at - prev_transaction.last_edit_at <= self.group_interval
1401                {
1402                    transaction = prev_transaction;
1403                    new_len -= 1;
1404                } else {
1405                    break;
1406                }
1407            }
1408        }
1409
1410        let (transactions_to_keep, transactions_to_merge) = self.undo_stack.split_at_mut(new_len);
1411        if let Some(last_transaction) = transactions_to_keep.last_mut() {
1412            if let Some(transaction) = transactions_to_merge.last() {
1413                last_transaction.last_edit_at = transaction.last_edit_at;
1414            }
1415        }
1416
1417        self.undo_stack.truncate(new_len);
1418        self.undo_stack.last().map(|t| t.id)
1419    }
1420}
1421
1422impl Excerpt {
1423    fn new(
1424        id: ExcerptId,
1425        buffer_id: usize,
1426        buffer: BufferSnapshot,
1427        range: Range<text::Anchor>,
1428        header_height: u8,
1429        render_header: Option<RenderHeaderFn>,
1430        has_trailing_newline: bool,
1431    ) -> Self {
1432        let mut text_summary =
1433            buffer.text_summary_for_range::<TextSummary, _>(range.to_offset(&buffer));
1434        if header_height > 0 {
1435            text_summary.first_line_chars = 0;
1436            text_summary.lines.row += header_height as u32;
1437            text_summary.lines_utf16.row += header_height as u32;
1438            text_summary.bytes += header_height as usize;
1439            text_summary.longest_row += header_height as u32;
1440        }
1441        if has_trailing_newline {
1442            text_summary.last_line_chars = 0;
1443            text_summary.lines.row += 1;
1444            text_summary.lines.column = 0;
1445            text_summary.lines_utf16.row += 1;
1446            text_summary.lines_utf16.column = 0;
1447            text_summary.bytes += 1;
1448        }
1449
1450        Excerpt {
1451            id,
1452            buffer_id,
1453            buffer,
1454            range,
1455            text_summary,
1456            header_height,
1457            render_header,
1458            has_trailing_newline,
1459        }
1460    }
1461
1462    fn header_summary(&self) -> TextSummary {
1463        TextSummary {
1464            bytes: self.header_height as usize,
1465            lines: Point::new(self.header_height as u32, 0),
1466            lines_utf16: PointUtf16::new(self.header_height as u32, 0),
1467            first_line_chars: 0,
1468            last_line_chars: 0,
1469            longest_row: 0,
1470            longest_row_chars: 0,
1471        }
1472    }
1473}
1474
1475impl sum_tree::Item for Excerpt {
1476    type Summary = ExcerptSummary;
1477
1478    fn summary(&self) -> Self::Summary {
1479        ExcerptSummary {
1480            excerpt_id: self.id.clone(),
1481            text: self.text_summary.clone(),
1482        }
1483    }
1484}
1485
1486impl sum_tree::Summary for ExcerptSummary {
1487    type Context = ();
1488
1489    fn add_summary(&mut self, summary: &Self, _: &()) {
1490        debug_assert!(summary.excerpt_id > self.excerpt_id);
1491        self.excerpt_id = summary.excerpt_id.clone();
1492        self.text.add_summary(&summary.text, &());
1493    }
1494}
1495
1496impl<'a> sum_tree::Dimension<'a, ExcerptSummary> for TextSummary {
1497    fn add_summary(&mut self, summary: &'a ExcerptSummary, _: &()) {
1498        *self += &summary.text;
1499    }
1500}
1501
1502impl<'a> sum_tree::Dimension<'a, ExcerptSummary> for usize {
1503    fn add_summary(&mut self, summary: &'a ExcerptSummary, _: &()) {
1504        *self += summary.text.bytes;
1505    }
1506}
1507
1508impl<'a> sum_tree::SeekTarget<'a, ExcerptSummary, ExcerptSummary> for usize {
1509    fn cmp(&self, cursor_location: &ExcerptSummary, _: &()) -> cmp::Ordering {
1510        Ord::cmp(self, &cursor_location.text.bytes)
1511    }
1512}
1513
1514impl<'a> sum_tree::SeekTarget<'a, ExcerptSummary, ExcerptSummary> for Option<&'a ExcerptId> {
1515    fn cmp(&self, cursor_location: &ExcerptSummary, _: &()) -> cmp::Ordering {
1516        Ord::cmp(self, &Some(&cursor_location.excerpt_id))
1517    }
1518}
1519
1520impl<'a> sum_tree::Dimension<'a, ExcerptSummary> for Point {
1521    fn add_summary(&mut self, summary: &'a ExcerptSummary, _: &()) {
1522        *self += summary.text.lines;
1523    }
1524}
1525
1526impl<'a> sum_tree::Dimension<'a, ExcerptSummary> for PointUtf16 {
1527    fn add_summary(&mut self, summary: &'a ExcerptSummary, _: &()) {
1528        *self += summary.text.lines_utf16
1529    }
1530}
1531
1532impl<'a> sum_tree::Dimension<'a, ExcerptSummary> for Option<&'a ExcerptId> {
1533    fn add_summary(&mut self, summary: &'a ExcerptSummary, _: &()) {
1534        *self = Some(&summary.excerpt_id);
1535    }
1536}
1537
1538impl<'a> MultiBufferChunks<'a> {
1539    pub fn offset(&self) -> usize {
1540        self.range.start
1541    }
1542
1543    pub fn seek(&mut self, offset: usize) {
1544        self.range.start = offset;
1545        self.cursor.seek_forward(&offset, Bias::Right, &());
1546        self.header_height = 0;
1547        self.excerpt_chunks = None;
1548        if let Some(excerpt) = self.cursor.item() {
1549            let buffer_range = excerpt.range.to_offset(&excerpt.buffer);
1550            self.header_height = excerpt.header_height;
1551            self.has_trailing_newline = excerpt.has_trailing_newline;
1552
1553            let buffer_start;
1554            let start_overshoot = self.range.start - self.cursor.start();
1555            if start_overshoot < excerpt.header_height as usize {
1556                self.header_height -= start_overshoot as u8;
1557                buffer_start = buffer_range.start;
1558            } else {
1559                buffer_start =
1560                    buffer_range.start + start_overshoot - excerpt.header_height as usize;
1561                self.header_height = 0;
1562            }
1563
1564            let buffer_end;
1565            let end_overshoot = self.range.end - self.cursor.start();
1566            if end_overshoot < excerpt.header_height as usize {
1567                self.header_height -= excerpt.header_height - end_overshoot as u8;
1568                buffer_end = buffer_start;
1569            } else {
1570                buffer_end = cmp::min(
1571                    buffer_range.end,
1572                    buffer_range.start + end_overshoot - excerpt.header_height as usize,
1573                );
1574            }
1575
1576            self.excerpt_chunks = Some(excerpt.buffer.chunks(buffer_start..buffer_end, self.theme));
1577        }
1578    }
1579}
1580
1581impl<'a> Iterator for MultiBufferChunks<'a> {
1582    type Item = Chunk<'a>;
1583
1584    fn next(&mut self) -> Option<Self::Item> {
1585        loop {
1586            if self.header_height > 0 {
1587                let chunk = Chunk {
1588                    text: unsafe {
1589                        std::str::from_utf8_unchecked(&NEWLINES[..self.header_height as usize])
1590                    },
1591                    ..Default::default()
1592                };
1593                self.range.start += self.header_height as usize;
1594                self.header_height = 0;
1595                return Some(chunk);
1596            }
1597
1598            if let Some(excerpt_chunks) = self.excerpt_chunks.as_mut() {
1599                if let Some(chunk) = excerpt_chunks.next() {
1600                    self.range.start += chunk.text.len();
1601                    return Some(chunk);
1602                }
1603                self.excerpt_chunks.take();
1604                if self.has_trailing_newline && self.cursor.end(&()) <= self.range.end {
1605                    self.range.start += 1;
1606                    return Some(Chunk {
1607                        text: "\n",
1608                        ..Default::default()
1609                    });
1610                }
1611            }
1612
1613            self.cursor.next(&());
1614            if *self.cursor.start() >= self.range.end {
1615                return None;
1616            }
1617
1618            let excerpt = self.cursor.item()?;
1619            let buffer_range = excerpt.range.to_offset(&excerpt.buffer);
1620
1621            let buffer_end = cmp::min(
1622                buffer_range.end,
1623                buffer_range.start + self.range.end
1624                    - excerpt.header_height as usize
1625                    - self.cursor.start(),
1626            );
1627
1628            self.header_height = excerpt.header_height;
1629            self.has_trailing_newline = excerpt.has_trailing_newline;
1630            self.excerpt_chunks = Some(
1631                excerpt
1632                    .buffer
1633                    .chunks(buffer_range.start..buffer_end, self.theme),
1634            );
1635        }
1636    }
1637}
1638
1639impl<'a> Iterator for MultiBufferBytes<'a> {
1640    type Item = &'a [u8];
1641
1642    fn next(&mut self) -> Option<Self::Item> {
1643        self.chunks.next().map(|chunk| chunk.text.as_bytes())
1644    }
1645}
1646
1647impl<'a> io::Read for MultiBufferBytes<'a> {
1648    fn read(&mut self, _: &mut [u8]) -> io::Result<usize> {
1649        todo!()
1650    }
1651}
1652
1653impl ToOffset for Point {
1654    fn to_offset<'a>(&self, snapshot: &MultiBufferSnapshot) -> usize {
1655        snapshot.point_to_offset(*self)
1656    }
1657}
1658
1659impl ToOffset for PointUtf16 {
1660    fn to_offset<'a>(&self, snapshot: &MultiBufferSnapshot) -> usize {
1661        snapshot.point_utf16_to_offset(*self)
1662    }
1663}
1664
1665impl ToOffset for usize {
1666    fn to_offset<'a>(&self, snapshot: &MultiBufferSnapshot) -> usize {
1667        assert!(*self <= snapshot.len(), "offset is out of range");
1668        *self
1669    }
1670}
1671
1672impl ToPoint for usize {
1673    fn to_point<'a>(&self, snapshot: &MultiBufferSnapshot) -> Point {
1674        snapshot.offset_to_point(*self)
1675    }
1676}
1677
1678impl ToPoint for Point {
1679    fn to_point<'a>(&self, _: &MultiBufferSnapshot) -> Point {
1680        *self
1681    }
1682}
1683
1684#[cfg(test)]
1685mod tests {
1686    use super::*;
1687    use gpui::{elements::Empty, Element, MutableAppContext};
1688    use language::Buffer;
1689    use rand::prelude::*;
1690    use std::env;
1691    use text::{Point, RandomCharIter};
1692    use util::test::sample_text;
1693
1694    #[gpui::test]
1695    fn test_singleton_multibuffer(cx: &mut MutableAppContext) {
1696        let buffer = cx.add_model(|cx| Buffer::new(0, sample_text(6, 6, 'a'), cx));
1697        let multibuffer = cx.add_model(|cx| MultiBuffer::singleton(buffer.clone(), cx));
1698        assert_eq!(
1699            multibuffer.read(cx).snapshot(cx).text(),
1700            buffer.read(cx).text()
1701        );
1702
1703        buffer.update(cx, |buffer, cx| buffer.edit([1..3], "XXX", cx));
1704        assert_eq!(
1705            multibuffer.read(cx).snapshot(cx).text(),
1706            buffer.read(cx).text()
1707        );
1708    }
1709
1710    #[gpui::test]
1711    fn test_excerpt_buffer(cx: &mut MutableAppContext) {
1712        let buffer_1 = cx.add_model(|cx| Buffer::new(0, sample_text(6, 6, 'a'), cx));
1713        let buffer_2 = cx.add_model(|cx| Buffer::new(0, sample_text(6, 6, 'g'), cx));
1714        let multibuffer = cx.add_model(|_| MultiBuffer::new(0));
1715
1716        let subscription = multibuffer.update(cx, |multibuffer, cx| {
1717            let subscription = multibuffer.subscribe();
1718            multibuffer.push_excerpt(
1719                ExcerptProperties {
1720                    buffer: &buffer_1,
1721                    range: Point::new(1, 2)..Point::new(2, 5),
1722                    header_height: 2,
1723                    render_header: Some(Arc::new(|_| Empty::new().named("header 1"))),
1724                },
1725                cx,
1726            );
1727            assert_eq!(
1728                subscription.consume().into_inner(),
1729                [Edit {
1730                    old: 0..0,
1731                    new: 0..13
1732                }]
1733            );
1734
1735            multibuffer.push_excerpt(
1736                ExcerptProperties {
1737                    buffer: &buffer_1,
1738                    range: Point::new(3, 3)..Point::new(4, 4),
1739                    header_height: 1,
1740                    render_header: Some(Arc::new(|_| Empty::new().named("header 2"))),
1741                },
1742                cx,
1743            );
1744            multibuffer.push_excerpt(
1745                ExcerptProperties {
1746                    buffer: &buffer_2,
1747                    range: Point::new(3, 1)..Point::new(3, 3),
1748                    header_height: 3,
1749                    render_header: Some(Arc::new(|_| Empty::new().named("header 3"))),
1750                },
1751                cx,
1752            );
1753            assert_eq!(
1754                subscription.consume().into_inner(),
1755                [Edit {
1756                    old: 13..13,
1757                    new: 13..29
1758                }]
1759            );
1760
1761            subscription
1762        });
1763
1764        assert_eq!(
1765            multibuffer.read(cx).snapshot(cx).text(),
1766            concat!(
1767                "\n",      // Preserve newlines
1768                "\n",      //
1769                "bbbb\n",  //
1770                "ccccc\n", //
1771                "\n",      //
1772                "ddd\n",   //
1773                "eeee\n",  //
1774                "\n",      //
1775                "\n",      //
1776                "\n",      //
1777                "jj\n"     //
1778            )
1779        );
1780
1781        {
1782            let snapshot = multibuffer.read(cx).read(cx);
1783            assert_eq!(
1784                snapshot
1785                    .excerpt_headers_in_range(0..snapshot.max_point().row + 1)
1786                    .map(|(rows, render)| (rows, render(cx).name().unwrap().to_string()))
1787                    .collect::<Vec<_>>(),
1788                &[
1789                    (0..2, "header 1".into()),
1790                    (4..5, "header 2".into()),
1791                    (7..10, "header 3".into())
1792                ]
1793            );
1794
1795            assert_eq!(
1796                snapshot
1797                    .excerpt_headers_in_range(1..5)
1798                    .map(|(rows, render)| (rows, render(cx).name().unwrap().to_string()))
1799                    .collect::<Vec<_>>(),
1800                &[(0..2, "header 1".into()), (4..5, "header 2".into())]
1801            );
1802
1803            assert_eq!(
1804                snapshot
1805                    .excerpt_headers_in_range(2..8)
1806                    .map(|(rows, render)| (rows, render(cx).name().unwrap().to_string()))
1807                    .collect::<Vec<_>>(),
1808                &[(4..5, "header 2".into()), (7..10, "header 3".into())]
1809            );
1810        }
1811
1812        buffer_1.update(cx, |buffer, cx| {
1813            buffer.edit(
1814                [
1815                    Point::new(0, 0)..Point::new(0, 0),
1816                    Point::new(2, 1)..Point::new(2, 3),
1817                ],
1818                "\n",
1819                cx,
1820            );
1821        });
1822
1823        assert_eq!(
1824            multibuffer.read(cx).snapshot(cx).text(),
1825            concat!(
1826                "\n",     // Preserve newlines
1827                "\n",     //
1828                "bbbb\n", //
1829                "c\n",    //
1830                "cc\n",   //
1831                "\n",     //
1832                "ddd\n",  //
1833                "eeee\n", //
1834                "\n",     //
1835                "\n",     //
1836                "\n",     //
1837                "jj\n"    //
1838            )
1839        );
1840
1841        assert_eq!(
1842            subscription.consume().into_inner(),
1843            [Edit {
1844                old: 8..10,
1845                new: 8..9
1846            }]
1847        );
1848    }
1849
1850    #[gpui::test]
1851    fn test_singleton_multibuffer_anchors(cx: &mut MutableAppContext) {
1852        let buffer = cx.add_model(|cx| Buffer::new(0, "abcd", cx));
1853        let multibuffer = cx.add_model(|cx| MultiBuffer::singleton(buffer.clone(), cx));
1854        let old_snapshot = multibuffer.read(cx).snapshot(cx);
1855        buffer.update(cx, |buffer, cx| {
1856            buffer.edit([0..0], "X", cx);
1857            buffer.edit([5..5], "Y", cx);
1858        });
1859        let new_snapshot = multibuffer.read(cx).snapshot(cx);
1860
1861        assert_eq!(old_snapshot.text(), "abcd");
1862        assert_eq!(new_snapshot.text(), "XabcdY");
1863
1864        assert_eq!(old_snapshot.anchor_before(0).to_offset(&new_snapshot), 0);
1865        assert_eq!(old_snapshot.anchor_after(0).to_offset(&new_snapshot), 1);
1866        assert_eq!(old_snapshot.anchor_before(4).to_offset(&new_snapshot), 5);
1867        assert_eq!(old_snapshot.anchor_after(4).to_offset(&new_snapshot), 6);
1868    }
1869
1870    #[gpui::test]
1871    fn test_multibuffer_anchors(cx: &mut MutableAppContext) {
1872        let buffer_1 = cx.add_model(|cx| Buffer::new(0, "abcd", cx));
1873        let buffer_2 = cx.add_model(|cx| Buffer::new(0, "efghi", cx));
1874        let multibuffer = cx.add_model(|cx| {
1875            let mut multibuffer = MultiBuffer::new(0);
1876            multibuffer.push_excerpt(
1877                ExcerptProperties {
1878                    buffer: &buffer_1,
1879                    range: 0..4,
1880                    header_height: 1,
1881                    render_header: None,
1882                },
1883                cx,
1884            );
1885            multibuffer.push_excerpt(
1886                ExcerptProperties {
1887                    buffer: &buffer_2,
1888                    range: 0..5,
1889                    header_height: 1,
1890                    render_header: None,
1891                },
1892                cx,
1893            );
1894            multibuffer
1895        });
1896        let old_snapshot = multibuffer.read(cx).snapshot(cx);
1897
1898        buffer_1.update(cx, |buffer, cx| {
1899            buffer.edit([0..0], "W", cx);
1900            buffer.edit([5..5], "X", cx);
1901        });
1902        buffer_2.update(cx, |buffer, cx| {
1903            buffer.edit([0..0], "Y", cx);
1904            buffer.edit([6..0], "Z", cx);
1905        });
1906        let new_snapshot = multibuffer.read(cx).snapshot(cx);
1907
1908        assert_eq!(old_snapshot.text(), "\nabcd\n\nefghi\n");
1909        assert_eq!(new_snapshot.text(), "\nWabcdX\n\nYefghiZ\n");
1910
1911        assert_eq!(old_snapshot.anchor_before(0).to_offset(&new_snapshot), 0);
1912        assert_eq!(old_snapshot.anchor_after(0).to_offset(&new_snapshot), 1);
1913        assert_eq!(old_snapshot.anchor_before(1).to_offset(&new_snapshot), 0);
1914        assert_eq!(old_snapshot.anchor_after(1).to_offset(&new_snapshot), 1);
1915        assert_eq!(old_snapshot.anchor_before(7).to_offset(&new_snapshot), 9);
1916        assert_eq!(old_snapshot.anchor_after(7).to_offset(&new_snapshot), 10);
1917    }
1918
1919    #[gpui::test(iterations = 100)]
1920    fn test_random_excerpts(cx: &mut MutableAppContext, mut rng: StdRng) {
1921        let operations = env::var("OPERATIONS")
1922            .map(|i| i.parse().expect("invalid `OPERATIONS` variable"))
1923            .unwrap_or(10);
1924
1925        let mut buffers: Vec<ModelHandle<Buffer>> = Vec::new();
1926        let list = cx.add_model(|_| MultiBuffer::new(0));
1927        let mut excerpt_ids = Vec::new();
1928        let mut expected_excerpts = Vec::new();
1929        let mut old_versions = Vec::new();
1930
1931        for _ in 0..operations {
1932            match rng.gen_range(0..100) {
1933                0..=19 if !buffers.is_empty() => {
1934                    let buffer = buffers.choose(&mut rng).unwrap();
1935                    buffer.update(cx, |buf, cx| buf.randomly_edit(&mut rng, 1, cx));
1936                }
1937                _ => {
1938                    let buffer_handle = if buffers.is_empty() || rng.gen_bool(0.4) {
1939                        let base_text = RandomCharIter::new(&mut rng).take(10).collect::<String>();
1940                        buffers.push(cx.add_model(|cx| Buffer::new(0, base_text, cx)));
1941                        buffers.last().unwrap()
1942                    } else {
1943                        buffers.choose(&mut rng).unwrap()
1944                    };
1945
1946                    let buffer = buffer_handle.read(cx);
1947                    let end_ix = buffer.clip_offset(rng.gen_range(0..=buffer.len()), Bias::Right);
1948                    let start_ix = buffer.clip_offset(rng.gen_range(0..=end_ix), Bias::Left);
1949                    let header_height = rng.gen_range(0..=5);
1950                    let anchor_range = buffer.anchor_before(start_ix)..buffer.anchor_after(end_ix);
1951                    log::info!(
1952                        "Pushing excerpt wih header {}, buffer {}: {:?}[{:?}] = {:?}",
1953                        header_height,
1954                        buffer_handle.id(),
1955                        buffer.text(),
1956                        start_ix..end_ix,
1957                        &buffer.text()[start_ix..end_ix]
1958                    );
1959
1960                    let excerpt_id = list.update(cx, |list, cx| {
1961                        list.push_excerpt(
1962                            ExcerptProperties {
1963                                buffer: &buffer_handle,
1964                                range: start_ix..end_ix,
1965                                header_height,
1966                                render_header: None,
1967                            },
1968                            cx,
1969                        )
1970                    });
1971                    excerpt_ids.push(excerpt_id);
1972                    expected_excerpts.push((buffer_handle.clone(), anchor_range, header_height));
1973                }
1974            }
1975
1976            if rng.gen_bool(0.3) {
1977                list.update(cx, |list, cx| {
1978                    old_versions.push((list.snapshot(cx), list.subscribe()));
1979                })
1980            }
1981
1982            let snapshot = list.read(cx).snapshot(cx);
1983
1984            let mut excerpt_starts = Vec::new();
1985            let mut expected_text = String::new();
1986            for (buffer, range, header_height) in &expected_excerpts {
1987                let buffer = buffer.read(cx);
1988                let buffer_range = range.to_offset(buffer);
1989
1990                for _ in 0..*header_height {
1991                    expected_text.push('\n');
1992                }
1993
1994                excerpt_starts.push(TextSummary::from(expected_text.as_str()));
1995                expected_text.extend(buffer.text_for_range(buffer_range.clone()));
1996                expected_text.push('\n');
1997            }
1998
1999            assert_eq!(snapshot.text(), expected_text);
2000
2001            let mut excerpt_starts = excerpt_starts.into_iter();
2002            for (buffer, range, _) in &expected_excerpts {
2003                let buffer_id = buffer.id();
2004                let buffer = buffer.read(cx);
2005                let buffer_range = range.to_offset(buffer);
2006                let buffer_start_point = buffer.offset_to_point(buffer_range.start);
2007                let buffer_start_point_utf16 =
2008                    buffer.text_summary_for_range::<PointUtf16, _>(0..buffer_range.start);
2009
2010                let excerpt_start = excerpt_starts.next().unwrap();
2011                let mut offset = excerpt_start.bytes;
2012                let mut buffer_offset = buffer_range.start;
2013                let mut point = excerpt_start.lines;
2014                let mut buffer_point = buffer_start_point;
2015                let mut point_utf16 = excerpt_start.lines_utf16;
2016                let mut buffer_point_utf16 = buffer_start_point_utf16;
2017                for byte in buffer.bytes_in_range(buffer_range.clone()).flatten() {
2018                    let left_offset = snapshot.clip_offset(offset, Bias::Left);
2019                    let right_offset = snapshot.clip_offset(offset, Bias::Right);
2020                    let buffer_left_offset = buffer.clip_offset(buffer_offset, Bias::Left);
2021                    let buffer_right_offset = buffer.clip_offset(buffer_offset, Bias::Right);
2022                    assert_eq!(
2023                        left_offset,
2024                        excerpt_start.bytes + (buffer_left_offset - buffer_range.start),
2025                        "clip_offset({:?}, Left). buffer: {:?}, buffer offset: {:?}",
2026                        offset,
2027                        buffer_id,
2028                        buffer_offset,
2029                    );
2030                    assert_eq!(
2031                        right_offset,
2032                        excerpt_start.bytes + (buffer_right_offset - buffer_range.start),
2033                        "clip_offset({:?}, Right). buffer: {:?}, buffer offset: {:?}",
2034                        offset,
2035                        buffer_id,
2036                        buffer_offset,
2037                    );
2038
2039                    let left_point = snapshot.clip_point(point, Bias::Left);
2040                    let right_point = snapshot.clip_point(point, Bias::Right);
2041                    let buffer_left_point = buffer.clip_point(buffer_point, Bias::Left);
2042                    let buffer_right_point = buffer.clip_point(buffer_point, Bias::Right);
2043                    assert_eq!(
2044                        left_point,
2045                        excerpt_start.lines + (buffer_left_point - buffer_start_point),
2046                        "clip_point({:?}, Left). buffer: {:?}, buffer point: {:?}",
2047                        point,
2048                        buffer_id,
2049                        buffer_point,
2050                    );
2051                    assert_eq!(
2052                        right_point,
2053                        excerpt_start.lines + (buffer_right_point - buffer_start_point),
2054                        "clip_point({:?}, Right). buffer: {:?}, buffer point: {:?}",
2055                        point,
2056                        buffer_id,
2057                        buffer_point,
2058                    );
2059
2060                    let left_point_utf16 = snapshot.clip_point_utf16(point_utf16, Bias::Left);
2061                    let right_point_utf16 = snapshot.clip_point_utf16(point_utf16, Bias::Right);
2062                    let buffer_left_point_utf16 =
2063                        buffer.clip_point_utf16(buffer_point_utf16, Bias::Left);
2064                    let buffer_right_point_utf16 =
2065                        buffer.clip_point_utf16(buffer_point_utf16, Bias::Right);
2066                    assert_eq!(
2067                        left_point_utf16,
2068                        excerpt_start.lines_utf16
2069                            + (buffer_left_point_utf16 - buffer_start_point_utf16),
2070                        "clip_point_utf16({:?}, Left). buffer: {:?}, buffer point_utf16: {:?}",
2071                        point_utf16,
2072                        buffer_id,
2073                        buffer_point_utf16,
2074                    );
2075                    assert_eq!(
2076                        right_point_utf16,
2077                        excerpt_start.lines_utf16
2078                            + (buffer_right_point_utf16 - buffer_start_point_utf16),
2079                        "clip_point_utf16({:?}, Right). buffer: {:?}, buffer point_utf16: {:?}",
2080                        point_utf16,
2081                        buffer_id,
2082                        buffer_point_utf16,
2083                    );
2084
2085                    assert_eq!(
2086                        snapshot.point_to_offset(left_point),
2087                        left_offset,
2088                        "point_to_offset({:?})",
2089                        left_point,
2090                    );
2091                    assert_eq!(
2092                        snapshot.offset_to_point(left_offset),
2093                        left_point,
2094                        "offset_to_point({:?})",
2095                        left_offset,
2096                    );
2097
2098                    offset += 1;
2099                    buffer_offset += 1;
2100                    if *byte == b'\n' {
2101                        point += Point::new(1, 0);
2102                        point_utf16 += PointUtf16::new(1, 0);
2103                        buffer_point += Point::new(1, 0);
2104                        buffer_point_utf16 += PointUtf16::new(1, 0);
2105                    } else {
2106                        point += Point::new(0, 1);
2107                        point_utf16 += PointUtf16::new(0, 1);
2108                        buffer_point += Point::new(0, 1);
2109                        buffer_point_utf16 += PointUtf16::new(0, 1);
2110                    }
2111                }
2112            }
2113
2114            for (row, line) in expected_text.split('\n').enumerate() {
2115                assert_eq!(
2116                    snapshot.line_len(row as u32),
2117                    line.len() as u32,
2118                    "line_len({}).",
2119                    row
2120                );
2121            }
2122
2123            for _ in 0..10 {
2124                let end_ix = snapshot.clip_offset(rng.gen_range(0..=snapshot.len()), Bias::Right);
2125                let start_ix = snapshot.clip_offset(rng.gen_range(0..=end_ix), Bias::Left);
2126
2127                assert_eq!(
2128                    snapshot
2129                        .text_for_range(start_ix..end_ix)
2130                        .collect::<String>(),
2131                    &expected_text[start_ix..end_ix],
2132                    "incorrect text for range {:?}",
2133                    start_ix..end_ix
2134                );
2135
2136                let expected_summary = TextSummary::from(&expected_text[start_ix..end_ix]);
2137                assert_eq!(
2138                    snapshot.text_summary_for_range::<TextSummary, _>(start_ix..end_ix),
2139                    expected_summary,
2140                    "incorrect summary for range {:?}",
2141                    start_ix..end_ix
2142                );
2143            }
2144        }
2145
2146        let snapshot = list.read(cx).snapshot(cx);
2147        for (old_snapshot, subscription) in old_versions {
2148            let edits = subscription.consume().into_inner();
2149
2150            log::info!(
2151                "applying edits since old text: {:?}: {:?}",
2152                old_snapshot.text(),
2153                edits,
2154            );
2155
2156            let mut text = old_snapshot.text();
2157            for edit in edits {
2158                let new_text: String = snapshot.text_for_range(edit.new.clone()).collect();
2159                text.replace_range(edit.new.start..edit.new.start + edit.old.len(), &new_text);
2160            }
2161            assert_eq!(text.to_string(), snapshot.text());
2162        }
2163    }
2164
2165    #[gpui::test]
2166    fn test_history(cx: &mut MutableAppContext) {
2167        let buffer_1 = cx.add_model(|cx| Buffer::new(0, "1234", cx));
2168        let buffer_2 = cx.add_model(|cx| Buffer::new(0, "5678", cx));
2169        let multibuffer = cx.add_model(|_| MultiBuffer::new(0));
2170        let group_interval = multibuffer.read(cx).history.group_interval;
2171        multibuffer.update(cx, |multibuffer, cx| {
2172            multibuffer.push_excerpt(
2173                ExcerptProperties {
2174                    buffer: &buffer_1,
2175                    range: 0..buffer_1.read(cx).len(),
2176                    header_height: 0,
2177                    render_header: None,
2178                },
2179                cx,
2180            );
2181            multibuffer.push_excerpt(
2182                ExcerptProperties {
2183                    buffer: &buffer_2,
2184                    range: 0..buffer_2.read(cx).len(),
2185                    header_height: 0,
2186                    render_header: None,
2187                },
2188                cx,
2189            );
2190        });
2191
2192        let mut now = Instant::now();
2193
2194        multibuffer.update(cx, |multibuffer, cx| {
2195            multibuffer.start_transaction_at(now, cx);
2196            multibuffer.edit(
2197                [
2198                    Point::new(0, 0)..Point::new(0, 0),
2199                    Point::new(1, 0)..Point::new(1, 0),
2200                ],
2201                "A",
2202                cx,
2203            );
2204            multibuffer.edit(
2205                [
2206                    Point::new(0, 1)..Point::new(0, 1),
2207                    Point::new(1, 1)..Point::new(1, 1),
2208                ],
2209                "B",
2210                cx,
2211            );
2212            multibuffer.end_transaction_at(now, cx);
2213            assert_eq!(multibuffer.read(cx).text(), "AB1234\nAB5678\n");
2214
2215            now += 2 * group_interval;
2216            multibuffer.start_transaction_at(now, cx);
2217            multibuffer.edit([2..2], "C", cx);
2218            multibuffer.end_transaction_at(now, cx);
2219            assert_eq!(multibuffer.read(cx).text(), "ABC1234\nAB5678\n");
2220
2221            multibuffer.undo(cx);
2222            assert_eq!(multibuffer.read(cx).text(), "AB1234\nAB5678\n");
2223
2224            multibuffer.undo(cx);
2225            assert_eq!(multibuffer.read(cx).text(), "1234\n5678\n");
2226
2227            multibuffer.redo(cx);
2228            assert_eq!(multibuffer.read(cx).text(), "AB1234\nAB5678\n");
2229
2230            multibuffer.redo(cx);
2231            assert_eq!(multibuffer.read(cx).text(), "ABC1234\nAB5678\n");
2232
2233            buffer_1.update(cx, |buffer_1, cx| buffer_1.undo(cx));
2234            assert_eq!(multibuffer.read(cx).text(), "AB1234\nAB5678\n");
2235
2236            multibuffer.undo(cx);
2237            assert_eq!(multibuffer.read(cx).text(), "1234\n5678\n");
2238
2239            multibuffer.redo(cx);
2240            assert_eq!(multibuffer.read(cx).text(), "AB1234\nAB5678\n");
2241
2242            multibuffer.redo(cx);
2243            assert_eq!(multibuffer.read(cx).text(), "ABC1234\nAB5678\n");
2244
2245            multibuffer.undo(cx);
2246            assert_eq!(multibuffer.read(cx).text(), "AB1234\nAB5678\n");
2247
2248            buffer_1.update(cx, |buffer_1, cx| buffer_1.redo(cx));
2249            assert_eq!(multibuffer.read(cx).text(), "ABC1234\nAB5678\n");
2250
2251            multibuffer.undo(cx);
2252            assert_eq!(multibuffer.read(cx).text(), "C1234\n5678\n");
2253        });
2254    }
2255}