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