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