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