multi_buffer.rs

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