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