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