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