multi_buffer.rs

   1mod anchor;
   2
   3pub use anchor::{Anchor, AnchorRangeExt};
   4use anyhow::Result;
   5use clock::ReplicaId;
   6use collections::HashMap;
   7use gpui::{AppContext, 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, io,
  15    iter::{self, FromIterator, Peekable},
  16    ops::{Range, Sub},
  17    sync::Arc,
  18    time::{Duration, Instant, SystemTime},
  19};
  20use sum_tree::{Bias, Cursor, SumTree};
  21use text::{
  22    locator::Locator,
  23    rope::TextDimension,
  24    subscription::{Subscription, Topic},
  25    AnchorRangeExt as _, Edit, Point, PointUtf16, TextSummary,
  26};
  27use theme::SyntaxTheme;
  28
  29const NEWLINES: &'static [u8] = &[b'\n'; u8::MAX as usize];
  30
  31pub type ExcerptId = Locator;
  32
  33pub struct MultiBuffer {
  34    snapshot: RefCell<MultiBufferSnapshot>,
  35    buffers: HashMap<usize, BufferState>,
  36    subscriptions: Topic,
  37    singleton: bool,
  38    replica_id: ReplicaId,
  39}
  40
  41pub trait ToOffset: 'static {
  42    fn to_offset(&self, snapshot: &MultiBufferSnapshot) -> usize;
  43}
  44
  45pub trait ToPoint: 'static {
  46    fn to_point(&self, snapshot: &MultiBufferSnapshot) -> Point;
  47}
  48
  49pub trait FromAnchor: 'static {
  50    fn from_anchor(anchor: &Anchor, snapshot: &MultiBufferSnapshot) -> Self;
  51}
  52
  53#[derive(Debug)]
  54struct BufferState {
  55    buffer: ModelHandle<Buffer>,
  56    last_version: clock::Global,
  57    last_parse_count: usize,
  58    last_diagnostics_update_count: usize,
  59    excerpts: Vec<ExcerptId>,
  60}
  61
  62#[derive(Clone, Default)]
  63pub struct MultiBufferSnapshot {
  64    excerpts: SumTree<Excerpt>,
  65    parse_count: usize,
  66    diagnostics_update_count: usize,
  67}
  68
  69pub struct ExcerptProperties<'a, T> {
  70    pub buffer: &'a ModelHandle<Buffer>,
  71    pub range: Range<T>,
  72    pub header_height: u8,
  73}
  74
  75#[derive(Clone)]
  76struct Excerpt {
  77    id: ExcerptId,
  78    buffer_id: usize,
  79    buffer: BufferSnapshot,
  80    range: Range<text::Anchor>,
  81    text_summary: TextSummary,
  82    header_height: u8,
  83    has_trailing_newline: bool,
  84}
  85
  86#[derive(Clone, Debug, Default)]
  87struct ExcerptSummary {
  88    excerpt_id: ExcerptId,
  89    text: TextSummary,
  90}
  91
  92pub struct MultiBufferChunks<'a> {
  93    range: Range<usize>,
  94    cursor: Cursor<'a, Excerpt, usize>,
  95    header_height: u8,
  96    has_trailing_newline: bool,
  97    excerpt_chunks: Option<BufferChunks<'a>>,
  98    theme: Option<&'a SyntaxTheme>,
  99}
 100
 101pub struct MultiBufferBytes<'a> {
 102    chunks: Peekable<MultiBufferChunks<'a>>,
 103}
 104
 105impl MultiBuffer {
 106    pub fn new(replica_id: ReplicaId) -> Self {
 107        Self {
 108            snapshot: Default::default(),
 109            buffers: Default::default(),
 110            subscriptions: Default::default(),
 111            singleton: false,
 112            replica_id,
 113        }
 114    }
 115
 116    pub fn singleton(buffer: ModelHandle<Buffer>, cx: &mut ModelContext<Self>) -> Self {
 117        let mut this = Self::new(buffer.read(cx).replica_id());
 118        this.singleton = true;
 119        this.push_excerpt(
 120            ExcerptProperties {
 121                buffer: &buffer,
 122                range: text::Anchor::min()..text::Anchor::max(),
 123                header_height: 0,
 124            },
 125            cx,
 126        );
 127        this
 128    }
 129
 130    pub fn build_simple(text: &str, cx: &mut MutableAppContext) -> ModelHandle<Self> {
 131        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx));
 132        cx.add_model(|cx| Self::singleton(buffer, cx))
 133    }
 134
 135    pub fn replica_id(&self) -> ReplicaId {
 136        self.replica_id
 137    }
 138
 139    pub fn transaction_group_interval(&self, cx: &AppContext) -> Duration {
 140        self.as_singleton()
 141            .unwrap()
 142            .read(cx)
 143            .transaction_group_interval()
 144    }
 145
 146    pub fn snapshot(&self, cx: &AppContext) -> MultiBufferSnapshot {
 147        self.sync(cx);
 148        self.snapshot.borrow().clone()
 149    }
 150
 151    pub fn read(&self, cx: &AppContext) -> Ref<MultiBufferSnapshot> {
 152        self.sync(cx);
 153        self.snapshot.borrow()
 154    }
 155
 156    pub fn as_singleton(&self) -> Option<&ModelHandle<Buffer>> {
 157        if self.buffers.len() == 1 {
 158            return Some(&self.buffers.values().next().unwrap().buffer);
 159        } else {
 160            None
 161        }
 162    }
 163
 164    pub fn subscribe(&mut self) -> Subscription {
 165        self.subscriptions.subscribe()
 166    }
 167
 168    pub fn edit<I, S, T>(&mut self, ranges: I, new_text: T, cx: &mut ModelContext<Self>)
 169    where
 170        I: IntoIterator<Item = Range<S>>,
 171        S: ToOffset,
 172        T: Into<String>,
 173    {
 174        self.edit_internal(ranges, new_text, false, cx)
 175    }
 176
 177    pub fn edit_with_autoindent<I, S, T>(
 178        &mut self,
 179        ranges: I,
 180        new_text: T,
 181        cx: &mut ModelContext<Self>,
 182    ) where
 183        I: IntoIterator<Item = Range<S>>,
 184        S: ToOffset,
 185        T: Into<String>,
 186    {
 187        self.edit_internal(ranges, new_text, true, cx)
 188    }
 189
 190    pub fn edit_internal<I, S, T>(
 191        &mut self,
 192        ranges_iter: I,
 193        new_text: T,
 194        autoindent: bool,
 195        cx: &mut ModelContext<Self>,
 196    ) where
 197        I: IntoIterator<Item = Range<S>>,
 198        S: ToOffset,
 199        T: Into<String>,
 200    {
 201        if let Some(buffer) = self.as_singleton() {
 202            let snapshot = self.read(cx);
 203            let ranges = ranges_iter
 204                .into_iter()
 205                .map(|range| range.start.to_offset(&snapshot)..range.end.to_offset(&snapshot));
 206            return buffer.update(cx, |buffer, cx| {
 207                if autoindent {
 208                    buffer.edit_with_autoindent(ranges, new_text, cx)
 209                } else {
 210                    buffer.edit(ranges, new_text, cx)
 211                }
 212            });
 213        }
 214
 215        let snapshot = self.read(cx);
 216        let mut buffer_edits: HashMap<usize, Vec<(Range<usize>, bool)>> = Default::default();
 217        let mut cursor = snapshot.excerpts.cursor::<usize>();
 218        for range in ranges_iter {
 219            let start = range.start.to_offset(&snapshot);
 220            let end = range.end.to_offset(&snapshot);
 221            cursor.seek(&start, Bias::Right, &());
 222            let start_excerpt = cursor.item().expect("start offset out of bounds");
 223            let start_overshoot =
 224                (start - cursor.start()).saturating_sub(start_excerpt.header_height as usize);
 225            let buffer_start =
 226                start_excerpt.range.start.to_offset(&start_excerpt.buffer) + start_overshoot;
 227
 228            cursor.seek(&end, Bias::Right, &());
 229            let end_excerpt = cursor.item().expect("end offset out of bounds");
 230            let end_overshoot =
 231                (end - cursor.start()).saturating_sub(end_excerpt.header_height as usize);
 232            let buffer_end = end_excerpt.range.start.to_offset(&end_excerpt.buffer) + end_overshoot;
 233
 234            if start_excerpt.id == end_excerpt.id {
 235                buffer_edits
 236                    .entry(start_excerpt.buffer_id)
 237                    .or_insert(Vec::new())
 238                    .push((buffer_start..buffer_end, true));
 239            } else {
 240                let start_excerpt_range =
 241                    buffer_start..start_excerpt.range.end.to_offset(&start_excerpt.buffer);
 242                let end_excerpt_range =
 243                    end_excerpt.range.start.to_offset(&end_excerpt.buffer)..buffer_end;
 244                buffer_edits
 245                    .entry(start_excerpt.buffer_id)
 246                    .or_insert(Vec::new())
 247                    .push((start_excerpt_range, true));
 248                buffer_edits
 249                    .entry(end_excerpt.buffer_id)
 250                    .or_insert(Vec::new())
 251                    .push((end_excerpt_range, false));
 252
 253                cursor.seek(&start, Bias::Right, &());
 254                cursor.next(&());
 255                while let Some(excerpt) = cursor.item() {
 256                    if excerpt.id == end_excerpt.id {
 257                        break;
 258                    }
 259
 260                    let excerpt_range = start_excerpt.range.end.to_offset(&start_excerpt.buffer)
 261                        ..start_excerpt.range.end.to_offset(&start_excerpt.buffer);
 262                    buffer_edits
 263                        .entry(excerpt.buffer_id)
 264                        .or_insert(Vec::new())
 265                        .push((excerpt_range, false));
 266                    cursor.next(&());
 267                }
 268            }
 269        }
 270
 271        let new_text = new_text.into();
 272        for (buffer_id, mut edits) in buffer_edits {
 273            edits.sort_unstable_by_key(|(range, _)| range.start);
 274            self.buffers[&buffer_id].buffer.update(cx, |buffer, cx| {
 275                let mut edits = edits.into_iter().peekable();
 276                let mut insertions = Vec::new();
 277                let mut deletions = Vec::new();
 278                while let Some((mut range, mut is_insertion)) = edits.next() {
 279                    while let Some((next_range, next_is_insertion)) = edits.peek() {
 280                        if range.end >= next_range.start {
 281                            range.end = cmp::max(next_range.end, range.end);
 282                            is_insertion |= *next_is_insertion;
 283                            edits.next();
 284                        } else {
 285                            break;
 286                        }
 287                    }
 288
 289                    if is_insertion {
 290                        insertions.push(
 291                            buffer.anchor_before(range.start)..buffer.anchor_before(range.end),
 292                        );
 293                    } else {
 294                        deletions.push(
 295                            buffer.anchor_before(range.start)..buffer.anchor_before(range.end),
 296                        );
 297                    }
 298                }
 299
 300                if autoindent {
 301                    buffer.edit_with_autoindent(deletions, "", cx);
 302                    buffer.edit_with_autoindent(insertions, new_text.clone(), cx);
 303                } else {
 304                    buffer.edit(deletions, "", cx);
 305                    buffer.edit(insertions, new_text.clone(), cx);
 306                }
 307            })
 308        }
 309    }
 310
 311    pub fn start_transaction(&mut self, cx: &mut ModelContext<Self>) -> Option<TransactionId> {
 312        self.start_transaction_at(Instant::now(), cx)
 313    }
 314
 315    pub(crate) fn start_transaction_at(
 316        &mut self,
 317        now: Instant,
 318        cx: &mut ModelContext<Self>,
 319    ) -> Option<TransactionId> {
 320        // TODO
 321        self.as_singleton()
 322            .unwrap()
 323            .update(cx, |buffer, _| buffer.start_transaction_at(now))
 324    }
 325
 326    pub fn end_transaction(&mut self, cx: &mut ModelContext<Self>) -> Option<TransactionId> {
 327        // TODO
 328        self.as_singleton()
 329            .unwrap()
 330            .update(cx, |buffer, cx| buffer.end_transaction(cx))
 331    }
 332
 333    pub(crate) fn end_transaction_at(
 334        &mut self,
 335        now: Instant,
 336        cx: &mut ModelContext<Self>,
 337    ) -> Option<TransactionId> {
 338        // TODO
 339        self.as_singleton()
 340            .unwrap()
 341            .update(cx, |buffer, cx| buffer.end_transaction_at(now, cx))
 342    }
 343
 344    pub fn set_active_selections(
 345        &mut self,
 346        selections: &[Selection<Anchor>],
 347        cx: &mut ModelContext<Self>,
 348    ) {
 349        let mut selections_by_buffer: HashMap<usize, Vec<Selection<text::Anchor>>> =
 350            Default::default();
 351        let snapshot = self.read(cx);
 352        let mut cursor = snapshot.excerpts.cursor::<Option<&ExcerptId>>();
 353        for selection in selections {
 354            cursor.seek(&Some(&selection.start.excerpt_id), Bias::Left, &());
 355            while let Some(excerpt) = cursor.item() {
 356                if excerpt.id > selection.end.excerpt_id {
 357                    break;
 358                }
 359
 360                let mut start = excerpt.range.start.clone();
 361                let mut end = excerpt.range.end.clone();
 362                if excerpt.id == selection.start.excerpt_id {
 363                    start = selection.start.text_anchor.clone();
 364                }
 365                if excerpt.id == selection.end.excerpt_id {
 366                    end = selection.end.text_anchor.clone();
 367                }
 368                selections_by_buffer
 369                    .entry(excerpt.buffer_id)
 370                    .or_default()
 371                    .push(Selection {
 372                        id: selection.id,
 373                        start,
 374                        end,
 375                        reversed: selection.reversed,
 376                        goal: selection.goal,
 377                    });
 378
 379                cursor.next(&());
 380            }
 381        }
 382
 383        for (buffer_id, mut selections) in selections_by_buffer {
 384            self.buffers[&buffer_id].buffer.update(cx, |buffer, cx| {
 385                selections.sort_unstable_by(|a, b| a.start.cmp(&b.start, buffer).unwrap());
 386                let mut selections = selections.into_iter().peekable();
 387                let merged_selections = Arc::from_iter(iter::from_fn(|| {
 388                    let mut selection = selections.next()?;
 389                    while let Some(next_selection) = selections.peek() {
 390                        if selection
 391                            .end
 392                            .cmp(&next_selection.start, buffer)
 393                            .unwrap()
 394                            .is_ge()
 395                        {
 396                            let next_selection = selections.next().unwrap();
 397                            if next_selection
 398                                .end
 399                                .cmp(&selection.end, buffer)
 400                                .unwrap()
 401                                .is_ge()
 402                            {
 403                                selection.end = next_selection.end;
 404                            }
 405                        } else {
 406                            break;
 407                        }
 408                    }
 409                    Some(selection)
 410                }));
 411                buffer.set_active_selections(merged_selections, cx);
 412            });
 413        }
 414    }
 415
 416    pub fn remove_active_selections(&mut self, cx: &mut ModelContext<Self>) {
 417        for buffer in self.buffers.values() {
 418            buffer
 419                .buffer
 420                .update(cx, |buffer, cx| buffer.remove_active_selections(cx));
 421        }
 422    }
 423
 424    pub fn undo(&mut self, cx: &mut ModelContext<Self>) -> Option<TransactionId> {
 425        // TODO
 426        self.as_singleton()
 427            .unwrap()
 428            .update(cx, |buffer, cx| buffer.undo(cx))
 429    }
 430
 431    pub fn redo(&mut self, cx: &mut ModelContext<Self>) -> Option<TransactionId> {
 432        // TODO
 433        self.as_singleton()
 434            .unwrap()
 435            .update(cx, |buffer, cx| buffer.redo(cx))
 436    }
 437
 438    pub fn push_excerpt<O>(
 439        &mut self,
 440        props: ExcerptProperties<O>,
 441        cx: &mut ModelContext<Self>,
 442    ) -> ExcerptId
 443    where
 444        O: text::ToOffset,
 445    {
 446        self.sync(cx);
 447
 448        let buffer = &props.buffer;
 449        cx.subscribe(buffer, Self::on_buffer_event).detach();
 450
 451        let buffer = props.buffer.read(cx);
 452        let range = buffer.anchor_before(&props.range.start)..buffer.anchor_after(&props.range.end);
 453        let mut snapshot = self.snapshot.borrow_mut();
 454        let prev_id = snapshot.excerpts.last().map(|e| &e.id);
 455        let id = ExcerptId::between(prev_id.unwrap_or(&ExcerptId::min()), &ExcerptId::max());
 456
 457        let edit_start = snapshot.excerpts.summary().text.bytes;
 458        let excerpt = Excerpt::new(
 459            id.clone(),
 460            props.buffer.id(),
 461            buffer.snapshot(),
 462            range,
 463            props.header_height,
 464            !self.singleton,
 465        );
 466        let edit = Edit {
 467            old: edit_start..edit_start,
 468            new: edit_start..edit_start + excerpt.text_summary.bytes,
 469        };
 470        snapshot.excerpts.push(excerpt, &());
 471        self.buffers
 472            .entry(props.buffer.id())
 473            .or_insert_with(|| BufferState {
 474                buffer: props.buffer.clone(),
 475                last_version: buffer.version(),
 476                last_parse_count: buffer.parse_count(),
 477                last_diagnostics_update_count: buffer.diagnostics_update_count(),
 478                excerpts: Default::default(),
 479            })
 480            .excerpts
 481            .push(id.clone());
 482
 483        self.subscriptions.publish_mut([edit]);
 484
 485        id
 486    }
 487
 488    fn on_buffer_event(
 489        &mut self,
 490        _: ModelHandle<Buffer>,
 491        event: &Event,
 492        cx: &mut ModelContext<Self>,
 493    ) {
 494        cx.emit(event.clone());
 495    }
 496
 497    pub fn save(
 498        &mut self,
 499        cx: &mut ModelContext<Self>,
 500    ) -> Result<Task<Result<(clock::Global, SystemTime)>>> {
 501        self.as_singleton()
 502            .unwrap()
 503            .update(cx, |buffer, cx| buffer.save(cx))
 504    }
 505
 506    pub fn language<'a>(&self, cx: &'a AppContext) -> Option<&'a Arc<Language>> {
 507        self.buffers
 508            .values()
 509            .next()
 510            .and_then(|state| state.buffer.read(cx).language())
 511    }
 512
 513    pub fn file<'a>(&self, cx: &'a AppContext) -> Option<&'a dyn File> {
 514        self.as_singleton().unwrap().read(cx).file()
 515    }
 516
 517    pub fn is_dirty(&self, cx: &AppContext) -> bool {
 518        self.as_singleton().unwrap().read(cx).is_dirty()
 519    }
 520
 521    pub fn has_conflict(&self, cx: &AppContext) -> bool {
 522        self.as_singleton().unwrap().read(cx).has_conflict()
 523    }
 524
 525    pub fn is_parsing(&self, cx: &AppContext) -> bool {
 526        self.as_singleton().unwrap().read(cx).is_parsing()
 527    }
 528
 529    fn sync(&self, cx: &AppContext) {
 530        let mut snapshot = self.snapshot.borrow_mut();
 531        let mut excerpts_to_edit = Vec::new();
 532        let mut reparsed = false;
 533        let mut diagnostics_updated = false;
 534        for buffer_state in self.buffers.values() {
 535            let buffer = buffer_state.buffer.read(cx);
 536            let buffer_edited = buffer.version().gt(&buffer_state.last_version);
 537            let buffer_reparsed = buffer.parse_count() > buffer_state.last_parse_count;
 538            let buffer_diagnostics_updated =
 539                buffer.diagnostics_update_count() > buffer_state.last_diagnostics_update_count;
 540            if buffer_edited || buffer_reparsed || buffer_diagnostics_updated {
 541                excerpts_to_edit.extend(
 542                    buffer_state
 543                        .excerpts
 544                        .iter()
 545                        .map(|excerpt_id| (excerpt_id, buffer_state, buffer_edited)),
 546                );
 547            }
 548
 549            reparsed |= buffer_reparsed;
 550            diagnostics_updated |= buffer_diagnostics_updated;
 551        }
 552        if reparsed {
 553            snapshot.parse_count += 1;
 554        }
 555        if diagnostics_updated {
 556            snapshot.diagnostics_update_count += 1;
 557        }
 558        excerpts_to_edit.sort_unstable_by_key(|(excerpt_id, _, _)| *excerpt_id);
 559
 560        let mut edits = Vec::new();
 561        let mut new_excerpts = SumTree::new();
 562        let mut cursor = snapshot.excerpts.cursor::<(Option<&ExcerptId>, usize)>();
 563
 564        for (id, buffer_state, buffer_edited) in excerpts_to_edit {
 565            new_excerpts.push_tree(cursor.slice(&Some(id), Bias::Left, &()), &());
 566            let old_excerpt = cursor.item().unwrap();
 567            let buffer = buffer_state.buffer.read(cx);
 568
 569            let mut new_excerpt;
 570            if buffer_edited {
 571                edits.extend(
 572                    buffer
 573                        .edits_since_in_range::<usize>(
 574                            old_excerpt.buffer.version(),
 575                            old_excerpt.range.clone(),
 576                        )
 577                        .map(|mut edit| {
 578                            let excerpt_old_start =
 579                                cursor.start().1 + old_excerpt.header_height as usize;
 580                            let excerpt_new_start = new_excerpts.summary().text.bytes
 581                                + old_excerpt.header_height as usize;
 582                            edit.old.start += excerpt_old_start;
 583                            edit.old.end += excerpt_old_start;
 584                            edit.new.start += excerpt_new_start;
 585                            edit.new.end += excerpt_new_start;
 586                            edit
 587                        }),
 588                );
 589
 590                new_excerpt = Excerpt::new(
 591                    id.clone(),
 592                    buffer_state.buffer.id(),
 593                    buffer.snapshot(),
 594                    old_excerpt.range.clone(),
 595                    old_excerpt.header_height,
 596                    !self.singleton,
 597                );
 598            } else {
 599                new_excerpt = old_excerpt.clone();
 600                new_excerpt.buffer = buffer.snapshot();
 601            }
 602
 603            new_excerpts.push(new_excerpt, &());
 604            cursor.next(&());
 605        }
 606        new_excerpts.push_tree(cursor.suffix(&()), &());
 607
 608        drop(cursor);
 609        snapshot.excerpts = new_excerpts;
 610
 611        self.subscriptions.publish(edits);
 612    }
 613}
 614
 615#[cfg(any(test, feature = "test-support"))]
 616impl MultiBuffer {
 617    pub fn randomly_edit<R: rand::Rng>(
 618        &mut self,
 619        rng: &mut R,
 620        count: usize,
 621        cx: &mut ModelContext<Self>,
 622    ) {
 623        self.as_singleton()
 624            .unwrap()
 625            .update(cx, |buffer, cx| buffer.randomly_edit(rng, count, cx));
 626        self.sync(cx);
 627    }
 628}
 629
 630impl Entity for MultiBuffer {
 631    type Event = language::Event;
 632}
 633
 634impl MultiBufferSnapshot {
 635    pub fn text(&self) -> String {
 636        self.chunks(0..self.len(), None)
 637            .map(|chunk| chunk.text)
 638            .collect()
 639    }
 640
 641    pub fn reversed_chars_at<'a, T: ToOffset>(
 642        &'a self,
 643        position: T,
 644    ) -> impl Iterator<Item = char> + 'a {
 645        // TODO
 646        let offset = position.to_offset(self);
 647        self.as_singleton().unwrap().reversed_chars_at(offset)
 648    }
 649
 650    pub fn chars_at<'a, T: ToOffset>(&'a self, position: T) -> impl Iterator<Item = char> + 'a {
 651        let offset = position.to_offset(self);
 652        self.text_for_range(offset..self.len())
 653            .flat_map(|chunk| chunk.chars())
 654    }
 655
 656    pub fn text_for_range<'a, T: ToOffset>(
 657        &'a self,
 658        range: Range<T>,
 659    ) -> impl Iterator<Item = &'a str> {
 660        self.chunks(range, None).map(|chunk| chunk.text)
 661    }
 662
 663    pub fn is_line_blank(&self, row: u32) -> bool {
 664        self.text_for_range(Point::new(row, 0)..Point::new(row, self.line_len(row)))
 665            .all(|chunk| chunk.matches(|c: char| !c.is_whitespace()).next().is_none())
 666    }
 667
 668    pub fn contains_str_at<T>(&self, position: T, needle: &str) -> bool
 669    where
 670        T: ToOffset,
 671    {
 672        let offset = position.to_offset(self);
 673        self.as_singleton().unwrap().contains_str_at(offset, needle)
 674    }
 675
 676    fn as_singleton(&self) -> Option<&BufferSnapshot> {
 677        let mut excerpts = self.excerpts.iter();
 678        let buffer = excerpts.next().map(|excerpt| &excerpt.buffer);
 679        if excerpts.next().is_none() {
 680            buffer
 681        } else {
 682            None
 683        }
 684    }
 685
 686    pub fn len(&self) -> usize {
 687        self.excerpts.summary().text.bytes
 688    }
 689
 690    pub fn clip_offset(&self, offset: usize, bias: Bias) -> usize {
 691        let mut cursor = self.excerpts.cursor::<usize>();
 692        cursor.seek(&offset, Bias::Right, &());
 693        if let Some(excerpt) = cursor.item() {
 694            let start_after_header = *cursor.start() + excerpt.header_height as usize;
 695            if offset < start_after_header {
 696                *cursor.start()
 697            } else {
 698                let excerpt_start = excerpt.range.start.to_offset(&excerpt.buffer);
 699                let buffer_offset = excerpt
 700                    .buffer
 701                    .clip_offset(excerpt_start + (offset - start_after_header), bias);
 702                let offset_in_excerpt = if buffer_offset > excerpt_start {
 703                    buffer_offset - excerpt_start
 704                } else {
 705                    0
 706                };
 707                start_after_header + offset_in_excerpt
 708            }
 709        } else {
 710            self.excerpts.summary().text.bytes
 711        }
 712    }
 713
 714    pub fn clip_point(&self, point: Point, bias: Bias) -> Point {
 715        let mut cursor = self.excerpts.cursor::<Point>();
 716        cursor.seek(&point, Bias::Right, &());
 717        if let Some(excerpt) = cursor.item() {
 718            let start_after_header = *cursor.start() + Point::new(excerpt.header_height as u32, 0);
 719            if point < start_after_header {
 720                *cursor.start()
 721            } else {
 722                let excerpt_start = excerpt.range.start.to_point(&excerpt.buffer);
 723                let buffer_point = excerpt
 724                    .buffer
 725                    .clip_point(excerpt_start + (point - start_after_header), bias);
 726                let point_in_excerpt = if buffer_point > excerpt_start {
 727                    buffer_point - excerpt_start
 728                } else {
 729                    Point::zero()
 730                };
 731                start_after_header + point_in_excerpt
 732            }
 733        } else {
 734            self.excerpts.summary().text.lines
 735        }
 736    }
 737
 738    pub fn clip_point_utf16(&self, point: PointUtf16, bias: Bias) -> PointUtf16 {
 739        let mut cursor = self.excerpts.cursor::<PointUtf16>();
 740        cursor.seek(&point, Bias::Right, &());
 741        if let Some(excerpt) = cursor.item() {
 742            let start_after_header =
 743                *cursor.start() + PointUtf16::new(excerpt.header_height as u32, 0);
 744            if point < start_after_header {
 745                *cursor.start()
 746            } else {
 747                let excerpt_start = excerpt
 748                    .buffer
 749                    .offset_to_point_utf16(excerpt.range.start.to_offset(&excerpt.buffer));
 750                let buffer_point = excerpt
 751                    .buffer
 752                    .clip_point_utf16(excerpt_start + (point - start_after_header), bias);
 753                let point_in_excerpt = if buffer_point > excerpt_start {
 754                    buffer_point - excerpt_start
 755                } else {
 756                    PointUtf16::new(0, 0)
 757                };
 758                start_after_header + point_in_excerpt
 759            }
 760        } else {
 761            self.excerpts.summary().text.lines_utf16
 762        }
 763    }
 764
 765    pub fn bytes_in_range<'a, T: ToOffset>(&'a self, range: Range<T>) -> MultiBufferBytes<'a> {
 766        MultiBufferBytes {
 767            chunks: self.chunks(range, None).peekable(),
 768        }
 769    }
 770
 771    pub fn chunks<'a, T: ToOffset>(
 772        &'a self,
 773        range: Range<T>,
 774        theme: Option<&'a SyntaxTheme>,
 775    ) -> MultiBufferChunks<'a> {
 776        let mut result = MultiBufferChunks {
 777            range: 0..range.end.to_offset(self),
 778            cursor: self.excerpts.cursor::<usize>(),
 779            header_height: 0,
 780            excerpt_chunks: None,
 781            has_trailing_newline: false,
 782            theme,
 783        };
 784        result.seek(range.start.to_offset(self));
 785        result
 786    }
 787
 788    pub fn offset_to_point(&self, offset: usize) -> Point {
 789        let mut cursor = self.excerpts.cursor::<(usize, Point)>();
 790        cursor.seek(&offset, Bias::Right, &());
 791        if let Some(excerpt) = cursor.item() {
 792            let (start_offset, start_point) = cursor.start();
 793            let overshoot = offset - start_offset;
 794            let header_height = excerpt.header_height as usize;
 795            if overshoot < header_height {
 796                *start_point
 797            } else {
 798                let excerpt_start_offset = excerpt.range.start.to_offset(&excerpt.buffer);
 799                let excerpt_start_point = excerpt.range.start.to_point(&excerpt.buffer);
 800                let buffer_point = excerpt
 801                    .buffer
 802                    .offset_to_point(excerpt_start_offset + (overshoot - header_height));
 803                *start_point
 804                    + Point::new(header_height as u32, 0)
 805                    + (buffer_point - excerpt_start_point)
 806            }
 807        } else {
 808            self.excerpts.summary().text.lines
 809        }
 810    }
 811
 812    pub fn point_to_offset(&self, point: Point) -> usize {
 813        let mut cursor = self.excerpts.cursor::<(Point, usize)>();
 814        cursor.seek(&point, Bias::Right, &());
 815        if let Some(excerpt) = cursor.item() {
 816            let (start_point, start_offset) = cursor.start();
 817            let overshoot = point - start_point;
 818            let header_height = Point::new(excerpt.header_height as u32, 0);
 819            if overshoot < header_height {
 820                *start_offset
 821            } else {
 822                let excerpt_start_offset = excerpt.range.start.to_offset(&excerpt.buffer);
 823                let excerpt_start_point = excerpt.range.start.to_point(&excerpt.buffer);
 824                let buffer_offset = excerpt
 825                    .buffer
 826                    .point_to_offset(excerpt_start_point + (overshoot - header_height));
 827                *start_offset + excerpt.header_height as usize + buffer_offset
 828                    - excerpt_start_offset
 829            }
 830        } else {
 831            self.excerpts.summary().text.bytes
 832        }
 833    }
 834
 835    pub fn point_utf16_to_offset(&self, point: PointUtf16) -> usize {
 836        let mut cursor = self.excerpts.cursor::<(PointUtf16, usize)>();
 837        cursor.seek(&point, Bias::Right, &());
 838        if let Some(excerpt) = cursor.item() {
 839            let (start_point, start_offset) = cursor.start();
 840            let overshoot = point - start_point;
 841            let header_height = PointUtf16::new(excerpt.header_height as u32, 0);
 842            if overshoot < header_height {
 843                *start_offset
 844            } else {
 845                let excerpt_start_offset = excerpt.range.start.to_offset(&excerpt.buffer);
 846                let excerpt_start_point = excerpt
 847                    .buffer
 848                    .offset_to_point_utf16(excerpt.range.start.to_offset(&excerpt.buffer));
 849                let buffer_offset = excerpt
 850                    .buffer
 851                    .point_utf16_to_offset(excerpt_start_point + (overshoot - header_height));
 852                *start_offset
 853                    + excerpt.header_height as usize
 854                    + (buffer_offset - excerpt_start_offset)
 855            }
 856        } else {
 857            self.excerpts.summary().text.bytes
 858        }
 859    }
 860
 861    pub fn indent_column_for_line(&self, row: u32) -> u32 {
 862        if let Some((buffer, range)) = self.buffer_line_for_row(row) {
 863            buffer
 864                .indent_column_for_line(range.start.row)
 865                .min(range.end.column)
 866                .saturating_sub(range.start.column)
 867        } else {
 868            0
 869        }
 870    }
 871
 872    pub fn line_len(&self, row: u32) -> u32 {
 873        if let Some((_, range)) = self.buffer_line_for_row(row) {
 874            range.end.column - range.start.column
 875        } else {
 876            0
 877        }
 878    }
 879
 880    fn buffer_line_for_row(&self, row: u32) -> Option<(&BufferSnapshot, Range<Point>)> {
 881        let mut cursor = self.excerpts.cursor::<Point>();
 882        cursor.seek(&Point::new(row, 0), Bias::Right, &());
 883        if let Some(excerpt) = cursor.item() {
 884            let overshoot = row - cursor.start().row;
 885            let header_height = excerpt.header_height as u32;
 886            if overshoot >= header_height {
 887                let excerpt_start = excerpt.range.start.to_point(&excerpt.buffer);
 888                let excerpt_end = excerpt.range.end.to_point(&excerpt.buffer);
 889                let buffer_row = excerpt_start.row + overshoot - header_height;
 890                let line_start = Point::new(buffer_row, 0);
 891                let line_end = Point::new(buffer_row, excerpt.buffer.line_len(buffer_row));
 892                return Some((
 893                    &excerpt.buffer,
 894                    line_start.max(excerpt_start)..line_end.min(excerpt_end),
 895                ));
 896            }
 897        }
 898        None
 899    }
 900
 901    pub fn max_point(&self) -> Point {
 902        self.text_summary().lines
 903    }
 904
 905    pub fn text_summary(&self) -> TextSummary {
 906        self.excerpts.summary().text
 907    }
 908
 909    pub fn text_summary_for_range<'a, D, O>(&'a self, range: Range<O>) -> D
 910    where
 911        D: TextDimension,
 912        O: ToOffset,
 913    {
 914        let mut summary = D::default();
 915        let mut range = range.start.to_offset(self)..range.end.to_offset(self);
 916        let mut cursor = self.excerpts.cursor::<usize>();
 917        cursor.seek(&range.start, Bias::Right, &());
 918        if let Some(excerpt) = cursor.item() {
 919            let start_after_header = cursor.start() + excerpt.header_height as usize;
 920            if range.start < start_after_header {
 921                let header_len = cmp::min(range.end, start_after_header) - range.start;
 922                summary.add_assign(&D::from_text_summary(&TextSummary {
 923                    bytes: header_len,
 924                    lines: Point::new(header_len as u32, 0),
 925                    lines_utf16: PointUtf16::new(header_len as u32, 0),
 926                    first_line_chars: 0,
 927                    last_line_chars: 0,
 928                    longest_row: 0,
 929                    longest_row_chars: 0,
 930                }));
 931                range.start = start_after_header;
 932                range.end = cmp::max(range.start, range.end);
 933            }
 934
 935            let mut end_before_newline = cursor.end(&());
 936            if excerpt.has_trailing_newline {
 937                end_before_newline -= 1;
 938            }
 939
 940            let excerpt_start = excerpt.range.start.to_offset(&excerpt.buffer);
 941            let start_in_excerpt = excerpt_start + (range.start - start_after_header);
 942            let end_in_excerpt =
 943                excerpt_start + (cmp::min(end_before_newline, range.end) - start_after_header);
 944            summary.add_assign(
 945                &excerpt
 946                    .buffer
 947                    .text_summary_for_range(start_in_excerpt..end_in_excerpt),
 948            );
 949
 950            if range.end > end_before_newline {
 951                summary.add_assign(&D::from_text_summary(&TextSummary {
 952                    bytes: 1,
 953                    lines: Point::new(1 as u32, 0),
 954                    lines_utf16: PointUtf16::new(1 as u32, 0),
 955                    first_line_chars: 0,
 956                    last_line_chars: 0,
 957                    longest_row: 0,
 958                    longest_row_chars: 0,
 959                }));
 960            }
 961
 962            cursor.next(&());
 963        }
 964
 965        if range.end > *cursor.start() {
 966            summary.add_assign(&D::from_text_summary(&cursor.summary::<_, TextSummary>(
 967                &range.end,
 968                Bias::Right,
 969                &(),
 970            )));
 971            if let Some(excerpt) = cursor.item() {
 972                let start_after_header = cursor.start() + excerpt.header_height as usize;
 973                let header_len =
 974                    cmp::min(range.end - cursor.start(), excerpt.header_height as usize);
 975                summary.add_assign(&D::from_text_summary(&TextSummary {
 976                    bytes: header_len,
 977                    lines: Point::new(header_len as u32, 0),
 978                    lines_utf16: PointUtf16::new(header_len as u32, 0),
 979                    first_line_chars: 0,
 980                    last_line_chars: 0,
 981                    longest_row: 0,
 982                    longest_row_chars: 0,
 983                }));
 984                range.end = cmp::max(start_after_header, range.end);
 985
 986                let excerpt_start = excerpt.range.start.to_offset(&excerpt.buffer);
 987                let end_in_excerpt = excerpt_start + (range.end - start_after_header);
 988                summary.add_assign(
 989                    &excerpt
 990                        .buffer
 991                        .text_summary_for_range(excerpt_start..end_in_excerpt),
 992                );
 993                cursor.next(&());
 994            }
 995        }
 996
 997        summary
 998    }
 999
1000    pub fn summary_for_anchor<D>(&self, anchor: &Anchor) -> D
1001    where
1002        D: TextDimension + Ord + Sub<D, Output = D>,
1003    {
1004        let mut cursor = self.excerpts.cursor::<ExcerptSummary>();
1005        cursor.seek(&Some(&anchor.excerpt_id), Bias::Left, &());
1006        if let Some(excerpt) = cursor.item() {
1007            if excerpt.id == anchor.excerpt_id {
1008                let mut excerpt_start = D::from_text_summary(&cursor.start().text);
1009                excerpt_start.add_summary(&excerpt.header_summary(), &());
1010                let excerpt_buffer_start = excerpt.range.start.summary::<D>(&excerpt.buffer);
1011                let buffer_point = anchor.text_anchor.summary::<D>(&excerpt.buffer);
1012                if buffer_point > excerpt_buffer_start {
1013                    excerpt_start.add_assign(&(buffer_point - excerpt_buffer_start));
1014                }
1015                return excerpt_start;
1016            }
1017        }
1018        D::from_text_summary(&cursor.start().text)
1019    }
1020
1021    pub fn summaries_for_anchors<'a, D, I>(&'a self, anchors: I) -> Vec<D>
1022    where
1023        D: TextDimension + Ord + Sub<D, Output = D>,
1024        I: 'a + IntoIterator<Item = &'a Anchor>,
1025    {
1026        let mut anchors = anchors.into_iter().peekable();
1027        let mut cursor = self.excerpts.cursor::<ExcerptSummary>();
1028        let mut summaries = Vec::new();
1029        while let Some(anchor) = anchors.peek() {
1030            let excerpt_id = &anchor.excerpt_id;
1031            let excerpt_anchors = iter::from_fn(|| {
1032                let anchor = anchors.peek()?;
1033                if anchor.excerpt_id == *excerpt_id {
1034                    Some(&anchors.next().unwrap().text_anchor)
1035                } else {
1036                    None
1037                }
1038            });
1039
1040            cursor.seek_forward(&Some(excerpt_id), Bias::Left, &());
1041            if let Some(excerpt) = cursor.item() {
1042                if excerpt.id == *excerpt_id {
1043                    let mut excerpt_start = D::from_text_summary(&cursor.start().text);
1044                    excerpt_start.add_summary(&excerpt.header_summary(), &());
1045                    let excerpt_buffer_start = excerpt.range.start.summary::<D>(&excerpt.buffer);
1046                    summaries.extend(
1047                        excerpt
1048                            .buffer
1049                            .summaries_for_anchors::<D, _>(excerpt_anchors)
1050                            .map(move |summary| {
1051                                let mut excerpt_start = excerpt_start.clone();
1052                                let excerpt_buffer_start = excerpt_buffer_start.clone();
1053                                if summary > excerpt_buffer_start {
1054                                    excerpt_start.add_assign(&(summary - excerpt_buffer_start));
1055                                }
1056                                excerpt_start
1057                            }),
1058                    );
1059                    continue;
1060                }
1061            }
1062
1063            let summary = D::from_text_summary(&cursor.start().text);
1064            summaries.extend(excerpt_anchors.map(|_| summary.clone()));
1065        }
1066
1067        summaries
1068    }
1069
1070    pub fn anchor_before<T: ToOffset>(&self, position: T) -> Anchor {
1071        self.anchor_at(position, Bias::Left)
1072    }
1073
1074    pub fn anchor_after<T: ToOffset>(&self, position: T) -> Anchor {
1075        self.anchor_at(position, Bias::Right)
1076    }
1077
1078    pub fn anchor_at<T: ToOffset>(&self, position: T, bias: Bias) -> Anchor {
1079        let offset = position.to_offset(self);
1080        let mut cursor = self.excerpts.cursor::<(usize, Option<&ExcerptId>)>();
1081        cursor.seek(&offset, bias, &());
1082        if let Some(excerpt) = cursor.item() {
1083            let start_after_header = cursor.start().0 + excerpt.header_height as usize;
1084            let mut end_before_newline = cursor.end(&()).0;
1085            if excerpt.has_trailing_newline {
1086                end_before_newline -= 1;
1087            }
1088
1089            let buffer_start = excerpt.range.start.to_offset(&excerpt.buffer);
1090            let overshoot = cmp::min(offset, end_before_newline).saturating_sub(start_after_header);
1091            Anchor {
1092                excerpt_id: excerpt.id.clone(),
1093                text_anchor: excerpt.buffer.anchor_at(buffer_start + overshoot, bias),
1094            }
1095        } else if offset == 0 && bias == Bias::Left {
1096            Anchor::min()
1097        } else {
1098            Anchor::max()
1099        }
1100    }
1101
1102    pub fn parse_count(&self) -> usize {
1103        self.parse_count
1104    }
1105
1106    pub fn enclosing_bracket_ranges<T: ToOffset>(
1107        &self,
1108        range: Range<T>,
1109    ) -> Option<(Range<usize>, Range<usize>)> {
1110        let range = range.start.to_offset(self)..range.end.to_offset(self);
1111        self.as_singleton().unwrap().enclosing_bracket_ranges(range)
1112    }
1113
1114    pub fn diagnostics_update_count(&self) -> usize {
1115        self.diagnostics_update_count
1116    }
1117
1118    pub fn language(&self) -> Option<&Arc<Language>> {
1119        self.excerpts
1120            .iter()
1121            .next()
1122            .and_then(|excerpt| excerpt.buffer.language())
1123    }
1124
1125    pub fn diagnostic_group<'a, O>(
1126        &'a self,
1127        group_id: usize,
1128    ) -> impl Iterator<Item = DiagnosticEntry<O>> + 'a
1129    where
1130        O: text::FromAnchor + 'a,
1131    {
1132        self.as_singleton().unwrap().diagnostic_group(group_id)
1133    }
1134
1135    pub fn diagnostics_in_range<'a, T, O>(
1136        &'a self,
1137        range: Range<T>,
1138    ) -> impl Iterator<Item = DiagnosticEntry<O>> + 'a
1139    where
1140        T: 'a + ToOffset,
1141        O: 'a + text::FromAnchor,
1142    {
1143        let range = range.start.to_offset(self)..range.end.to_offset(self);
1144        self.as_singleton().unwrap().diagnostics_in_range(range)
1145    }
1146
1147    pub fn range_for_syntax_ancestor<T: ToOffset>(&self, range: Range<T>) -> Option<Range<usize>> {
1148        let range = range.start.to_offset(self)..range.end.to_offset(self);
1149        self.as_singleton()
1150            .unwrap()
1151            .range_for_syntax_ancestor(range)
1152    }
1153
1154    fn buffer_snapshot_for_excerpt<'a>(
1155        &'a self,
1156        excerpt_id: &'a ExcerptId,
1157    ) -> Option<&'a BufferSnapshot> {
1158        let mut cursor = self.excerpts.cursor::<Option<&ExcerptId>>();
1159        cursor.seek(&Some(excerpt_id), Bias::Left, &());
1160        if let Some(excerpt) = cursor.item() {
1161            if excerpt.id == *excerpt_id {
1162                return Some(&excerpt.buffer);
1163            }
1164        }
1165        None
1166    }
1167
1168    pub fn remote_selections_in_range<'a>(
1169        &'a self,
1170        range: &'a Range<Anchor>,
1171    ) -> impl 'a + Iterator<Item = (ReplicaId, Selection<Anchor>)> {
1172        let mut cursor = self.excerpts.cursor::<Option<&ExcerptId>>();
1173        cursor.seek(&Some(&range.start.excerpt_id), Bias::Left, &());
1174        cursor
1175            .take_while(move |excerpt| excerpt.id <= range.end.excerpt_id)
1176            .flat_map(move |excerpt| {
1177                let mut query_range = excerpt.range.start.clone()..excerpt.range.end.clone();
1178                if excerpt.id == range.start.excerpt_id {
1179                    query_range.start = range.start.text_anchor.clone();
1180                }
1181                if excerpt.id == range.end.excerpt_id {
1182                    query_range.end = range.end.text_anchor.clone();
1183                }
1184
1185                excerpt
1186                    .buffer
1187                    .remote_selections_in_range(query_range)
1188                    .flat_map(move |(replica_id, selections)| {
1189                        selections.map(move |selection| {
1190                            let mut start = Anchor {
1191                                excerpt_id: excerpt.id.clone(),
1192                                text_anchor: selection.start.clone(),
1193                            };
1194                            let mut end = Anchor {
1195                                excerpt_id: excerpt.id.clone(),
1196                                text_anchor: selection.end.clone(),
1197                            };
1198                            if range.start.cmp(&start, self).unwrap().is_gt() {
1199                                start = range.start.clone();
1200                            }
1201                            if range.end.cmp(&end, self).unwrap().is_lt() {
1202                                end = range.end.clone();
1203                            }
1204
1205                            (
1206                                replica_id,
1207                                Selection {
1208                                    id: selection.id,
1209                                    start,
1210                                    end,
1211                                    reversed: selection.reversed,
1212                                    goal: selection.goal,
1213                                },
1214                            )
1215                        })
1216                    })
1217            })
1218    }
1219}
1220
1221impl Excerpt {
1222    fn new(
1223        id: ExcerptId,
1224        buffer_id: usize,
1225        buffer: BufferSnapshot,
1226        range: Range<text::Anchor>,
1227        header_height: u8,
1228        has_trailing_newline: bool,
1229    ) -> Self {
1230        let mut text_summary =
1231            buffer.text_summary_for_range::<TextSummary, _>(range.to_offset(&buffer));
1232        if header_height > 0 {
1233            text_summary.first_line_chars = 0;
1234            text_summary.lines.row += header_height as u32;
1235            text_summary.lines_utf16.row += header_height as u32;
1236            text_summary.bytes += header_height as usize;
1237            text_summary.longest_row += header_height as u32;
1238        }
1239        if has_trailing_newline {
1240            text_summary.last_line_chars = 0;
1241            text_summary.lines.row += 1;
1242            text_summary.lines.column = 0;
1243            text_summary.lines_utf16.row += 1;
1244            text_summary.lines_utf16.column = 0;
1245            text_summary.bytes += 1;
1246        }
1247
1248        Excerpt {
1249            id,
1250            buffer_id,
1251            buffer,
1252            range,
1253            text_summary,
1254            header_height,
1255            has_trailing_newline,
1256        }
1257    }
1258
1259    fn header_summary(&self) -> TextSummary {
1260        TextSummary {
1261            bytes: self.header_height as usize,
1262            lines: Point::new(self.header_height as u32, 0),
1263            lines_utf16: PointUtf16::new(self.header_height as u32, 0),
1264            first_line_chars: 0,
1265            last_line_chars: 0,
1266            longest_row: 0,
1267            longest_row_chars: 0,
1268        }
1269    }
1270}
1271
1272impl sum_tree::Item for Excerpt {
1273    type Summary = ExcerptSummary;
1274
1275    fn summary(&self) -> Self::Summary {
1276        ExcerptSummary {
1277            excerpt_id: self.id.clone(),
1278            text: self.text_summary.clone(),
1279        }
1280    }
1281}
1282
1283impl sum_tree::Summary for ExcerptSummary {
1284    type Context = ();
1285
1286    fn add_summary(&mut self, summary: &Self, _: &()) {
1287        debug_assert!(summary.excerpt_id > self.excerpt_id);
1288        self.excerpt_id = summary.excerpt_id.clone();
1289        self.text.add_summary(&summary.text, &());
1290    }
1291}
1292
1293impl<'a> sum_tree::Dimension<'a, ExcerptSummary> for TextSummary {
1294    fn add_summary(&mut self, summary: &'a ExcerptSummary, _: &()) {
1295        *self += &summary.text;
1296    }
1297}
1298
1299impl<'a> sum_tree::Dimension<'a, ExcerptSummary> for usize {
1300    fn add_summary(&mut self, summary: &'a ExcerptSummary, _: &()) {
1301        *self += summary.text.bytes;
1302    }
1303}
1304
1305impl<'a> sum_tree::SeekTarget<'a, ExcerptSummary, ExcerptSummary> for usize {
1306    fn cmp(&self, cursor_location: &ExcerptSummary, _: &()) -> cmp::Ordering {
1307        Ord::cmp(self, &cursor_location.text.bytes)
1308    }
1309}
1310
1311impl<'a> sum_tree::SeekTarget<'a, ExcerptSummary, ExcerptSummary> for Option<&'a ExcerptId> {
1312    fn cmp(&self, cursor_location: &ExcerptSummary, _: &()) -> cmp::Ordering {
1313        Ord::cmp(self, &Some(&cursor_location.excerpt_id))
1314    }
1315}
1316
1317impl<'a> sum_tree::Dimension<'a, ExcerptSummary> for Point {
1318    fn add_summary(&mut self, summary: &'a ExcerptSummary, _: &()) {
1319        *self += summary.text.lines;
1320    }
1321}
1322
1323impl<'a> sum_tree::Dimension<'a, ExcerptSummary> for PointUtf16 {
1324    fn add_summary(&mut self, summary: &'a ExcerptSummary, _: &()) {
1325        *self += summary.text.lines_utf16
1326    }
1327}
1328
1329impl<'a> sum_tree::Dimension<'a, ExcerptSummary> for Option<&'a ExcerptId> {
1330    fn add_summary(&mut self, summary: &'a ExcerptSummary, _: &()) {
1331        *self = Some(&summary.excerpt_id);
1332    }
1333}
1334
1335impl<'a> MultiBufferChunks<'a> {
1336    pub fn offset(&self) -> usize {
1337        self.range.start
1338    }
1339
1340    pub fn seek(&mut self, offset: usize) {
1341        self.range.start = offset;
1342        self.cursor.seek_forward(&offset, Bias::Right, &());
1343        self.header_height = 0;
1344        self.excerpt_chunks = None;
1345        if let Some(excerpt) = self.cursor.item() {
1346            let buffer_range = excerpt.range.to_offset(&excerpt.buffer);
1347            self.header_height = excerpt.header_height;
1348            self.has_trailing_newline = excerpt.has_trailing_newline;
1349
1350            let buffer_start;
1351            let start_overshoot = self.range.start - self.cursor.start();
1352            if start_overshoot < excerpt.header_height as usize {
1353                self.header_height -= start_overshoot as u8;
1354                buffer_start = buffer_range.start;
1355            } else {
1356                buffer_start =
1357                    buffer_range.start + start_overshoot - excerpt.header_height as usize;
1358                self.header_height = 0;
1359            }
1360
1361            let buffer_end;
1362            let end_overshoot = self.range.end - self.cursor.start();
1363            if end_overshoot < excerpt.header_height as usize {
1364                self.header_height -= excerpt.header_height - end_overshoot as u8;
1365                buffer_end = buffer_start;
1366            } else {
1367                buffer_end = cmp::min(
1368                    buffer_range.end,
1369                    buffer_range.start + end_overshoot - excerpt.header_height as usize,
1370                );
1371            }
1372
1373            self.excerpt_chunks = Some(excerpt.buffer.chunks(buffer_start..buffer_end, self.theme));
1374        }
1375    }
1376}
1377
1378impl<'a> Iterator for MultiBufferChunks<'a> {
1379    type Item = Chunk<'a>;
1380
1381    fn next(&mut self) -> Option<Self::Item> {
1382        loop {
1383            if self.header_height > 0 {
1384                let chunk = Chunk {
1385                    text: unsafe {
1386                        std::str::from_utf8_unchecked(&NEWLINES[..self.header_height as usize])
1387                    },
1388                    ..Default::default()
1389                };
1390                self.range.start += self.header_height as usize;
1391                self.header_height = 0;
1392                return Some(chunk);
1393            }
1394
1395            if let Some(excerpt_chunks) = self.excerpt_chunks.as_mut() {
1396                if let Some(chunk) = excerpt_chunks.next() {
1397                    self.range.start += chunk.text.len();
1398                    return Some(chunk);
1399                }
1400                self.excerpt_chunks.take();
1401                if self.has_trailing_newline && self.cursor.end(&()) <= self.range.end {
1402                    self.range.start += 1;
1403                    return Some(Chunk {
1404                        text: "\n",
1405                        ..Default::default()
1406                    });
1407                }
1408            }
1409
1410            self.cursor.next(&());
1411            if *self.cursor.start() >= self.range.end {
1412                return None;
1413            }
1414
1415            let excerpt = self.cursor.item()?;
1416            let buffer_range = excerpt.range.to_offset(&excerpt.buffer);
1417
1418            let buffer_end = cmp::min(
1419                buffer_range.end,
1420                buffer_range.start + self.range.end
1421                    - excerpt.header_height as usize
1422                    - self.cursor.start(),
1423            );
1424
1425            self.header_height = excerpt.header_height;
1426            self.has_trailing_newline = excerpt.has_trailing_newline;
1427            self.excerpt_chunks = Some(
1428                excerpt
1429                    .buffer
1430                    .chunks(buffer_range.start..buffer_end, self.theme),
1431            );
1432        }
1433    }
1434}
1435
1436impl<'a> Iterator for MultiBufferBytes<'a> {
1437    type Item = &'a [u8];
1438
1439    fn next(&mut self) -> Option<Self::Item> {
1440        self.chunks.next().map(|chunk| chunk.text.as_bytes())
1441    }
1442}
1443
1444impl<'a> io::Read for MultiBufferBytes<'a> {
1445    fn read(&mut self, _: &mut [u8]) -> io::Result<usize> {
1446        todo!()
1447    }
1448}
1449
1450impl ToOffset for Point {
1451    fn to_offset<'a>(&self, snapshot: &MultiBufferSnapshot) -> usize {
1452        snapshot.point_to_offset(*self)
1453    }
1454}
1455
1456impl ToOffset for PointUtf16 {
1457    fn to_offset<'a>(&self, snapshot: &MultiBufferSnapshot) -> usize {
1458        snapshot.point_utf16_to_offset(*self)
1459    }
1460}
1461
1462impl ToOffset for usize {
1463    fn to_offset<'a>(&self, snapshot: &MultiBufferSnapshot) -> usize {
1464        assert!(*self <= snapshot.len(), "offset is out of range");
1465        *self
1466    }
1467}
1468
1469impl ToPoint for usize {
1470    fn to_point<'a>(&self, snapshot: &MultiBufferSnapshot) -> Point {
1471        snapshot.offset_to_point(*self)
1472    }
1473}
1474
1475impl ToPoint for Point {
1476    fn to_point<'a>(&self, _: &MultiBufferSnapshot) -> Point {
1477        *self
1478    }
1479}
1480
1481#[cfg(test)]
1482mod tests {
1483    use super::*;
1484    use gpui::MutableAppContext;
1485    use language::Buffer;
1486    use rand::prelude::*;
1487    use std::env;
1488    use text::{Point, RandomCharIter};
1489    use util::test::sample_text;
1490
1491    #[gpui::test]
1492    fn test_singleton_multibuffer(cx: &mut MutableAppContext) {
1493        let buffer = cx.add_model(|cx| Buffer::new(0, sample_text(6, 6, 'a'), cx));
1494        let multibuffer = cx.add_model(|cx| MultiBuffer::singleton(buffer.clone(), cx));
1495        assert_eq!(
1496            multibuffer.read(cx).snapshot(cx).text(),
1497            buffer.read(cx).text()
1498        );
1499
1500        buffer.update(cx, |buffer, cx| buffer.edit([1..3], "XXX", cx));
1501        assert_eq!(
1502            multibuffer.read(cx).snapshot(cx).text(),
1503            buffer.read(cx).text()
1504        );
1505    }
1506
1507    #[gpui::test]
1508    fn test_excerpt_buffer(cx: &mut MutableAppContext) {
1509        let buffer_1 = cx.add_model(|cx| Buffer::new(0, sample_text(6, 6, 'a'), cx));
1510        let buffer_2 = cx.add_model(|cx| Buffer::new(0, sample_text(6, 6, 'g'), cx));
1511
1512        let multibuffer = cx.add_model(|_| MultiBuffer::new(0));
1513
1514        let subscription = multibuffer.update(cx, |multibuffer, cx| {
1515            let subscription = multibuffer.subscribe();
1516            multibuffer.push_excerpt(
1517                ExcerptProperties {
1518                    buffer: &buffer_1,
1519                    range: Point::new(1, 2)..Point::new(2, 5),
1520                    header_height: 2,
1521                },
1522                cx,
1523            );
1524            assert_eq!(
1525                subscription.consume().into_inner(),
1526                [Edit {
1527                    old: 0..0,
1528                    new: 0..13
1529                }]
1530            );
1531
1532            multibuffer.push_excerpt(
1533                ExcerptProperties {
1534                    buffer: &buffer_1,
1535                    range: Point::new(3, 3)..Point::new(4, 4),
1536                    header_height: 1,
1537                },
1538                cx,
1539            );
1540            multibuffer.push_excerpt(
1541                ExcerptProperties {
1542                    buffer: &buffer_2,
1543                    range: Point::new(3, 1)..Point::new(3, 3),
1544                    header_height: 3,
1545                },
1546                cx,
1547            );
1548            assert_eq!(
1549                subscription.consume().into_inner(),
1550                [Edit {
1551                    old: 13..13,
1552                    new: 13..29
1553                }]
1554            );
1555
1556            subscription
1557        });
1558
1559        assert_eq!(
1560            multibuffer.read(cx).snapshot(cx).text(),
1561            concat!(
1562                "\n",      // Preserve newlines
1563                "\n",      //
1564                "bbbb\n",  //
1565                "ccccc\n", //
1566                "\n",      //
1567                "ddd\n",   //
1568                "eeee\n",  //
1569                "\n",      //
1570                "\n",      //
1571                "\n",      //
1572                "jj\n"     //
1573            )
1574        );
1575
1576        buffer_1.update(cx, |buffer, cx| {
1577            buffer.edit(
1578                [
1579                    Point::new(0, 0)..Point::new(0, 0),
1580                    Point::new(2, 1)..Point::new(2, 3),
1581                ],
1582                "\n",
1583                cx,
1584            );
1585        });
1586
1587        assert_eq!(
1588            multibuffer.read(cx).snapshot(cx).text(),
1589            concat!(
1590                "\n",     // Preserve newlines
1591                "\n",     //
1592                "bbbb\n", //
1593                "c\n",    //
1594                "cc\n",   //
1595                "\n",     //
1596                "ddd\n",  //
1597                "eeee\n", //
1598                "\n",     //
1599                "\n",     //
1600                "\n",     //
1601                "jj\n"    //
1602            )
1603        );
1604
1605        assert_eq!(
1606            subscription.consume().into_inner(),
1607            [Edit {
1608                old: 8..10,
1609                new: 8..9
1610            }]
1611        );
1612    }
1613
1614    #[gpui::test(iterations = 100)]
1615    fn test_random_excerpts(cx: &mut MutableAppContext, mut rng: StdRng) {
1616        let operations = env::var("OPERATIONS")
1617            .map(|i| i.parse().expect("invalid `OPERATIONS` variable"))
1618            .unwrap_or(10);
1619
1620        let mut buffers: Vec<ModelHandle<Buffer>> = Vec::new();
1621        let list = cx.add_model(|_| MultiBuffer::new(0));
1622        let mut excerpt_ids = Vec::new();
1623        let mut expected_excerpts = Vec::new();
1624        let mut old_versions = Vec::new();
1625
1626        for _ in 0..operations {
1627            match rng.gen_range(0..100) {
1628                0..=19 if !buffers.is_empty() => {
1629                    let buffer = buffers.choose(&mut rng).unwrap();
1630                    buffer.update(cx, |buf, cx| buf.randomly_edit(&mut rng, 1, cx));
1631                }
1632                _ => {
1633                    let buffer_handle = if buffers.is_empty() || rng.gen_bool(0.4) {
1634                        let base_text = RandomCharIter::new(&mut rng).take(10).collect::<String>();
1635                        buffers.push(cx.add_model(|cx| Buffer::new(0, base_text, cx)));
1636                        buffers.last().unwrap()
1637                    } else {
1638                        buffers.choose(&mut rng).unwrap()
1639                    };
1640
1641                    let buffer = buffer_handle.read(cx);
1642                    let end_ix = buffer.clip_offset(rng.gen_range(0..=buffer.len()), Bias::Right);
1643                    let start_ix = buffer.clip_offset(rng.gen_range(0..=end_ix), Bias::Left);
1644                    let header_height = rng.gen_range(0..=5);
1645                    let anchor_range = buffer.anchor_before(start_ix)..buffer.anchor_after(end_ix);
1646                    log::info!(
1647                        "Pushing excerpt wih header {}, buffer {}: {:?}[{:?}] = {:?}",
1648                        header_height,
1649                        buffer_handle.id(),
1650                        buffer.text(),
1651                        start_ix..end_ix,
1652                        &buffer.text()[start_ix..end_ix]
1653                    );
1654
1655                    let excerpt_id = list.update(cx, |list, cx| {
1656                        list.push_excerpt(
1657                            ExcerptProperties {
1658                                buffer: &buffer_handle,
1659                                range: start_ix..end_ix,
1660                                header_height,
1661                            },
1662                            cx,
1663                        )
1664                    });
1665                    excerpt_ids.push(excerpt_id);
1666                    expected_excerpts.push((buffer_handle.clone(), anchor_range, header_height));
1667                }
1668            }
1669
1670            if rng.gen_bool(0.3) {
1671                list.update(cx, |list, cx| {
1672                    old_versions.push((list.snapshot(cx), list.subscribe()));
1673                })
1674            }
1675
1676            let snapshot = list.read(cx).snapshot(cx);
1677
1678            let mut excerpt_starts = Vec::new();
1679            let mut expected_text = String::new();
1680            for (buffer, range, header_height) in &expected_excerpts {
1681                let buffer = buffer.read(cx);
1682                let buffer_range = range.to_offset(buffer);
1683
1684                for _ in 0..*header_height {
1685                    expected_text.push('\n');
1686                }
1687
1688                excerpt_starts.push(TextSummary::from(expected_text.as_str()));
1689                expected_text.extend(buffer.text_for_range(buffer_range.clone()));
1690                expected_text.push('\n');
1691            }
1692
1693            assert_eq!(snapshot.text(), expected_text);
1694
1695            let mut excerpt_starts = excerpt_starts.into_iter();
1696            for (buffer, range, _) in &expected_excerpts {
1697                let buffer_id = buffer.id();
1698                let buffer = buffer.read(cx);
1699                let buffer_range = range.to_offset(buffer);
1700                let buffer_start_point = buffer.offset_to_point(buffer_range.start);
1701                let buffer_start_point_utf16 =
1702                    buffer.text_summary_for_range::<PointUtf16, _>(0..buffer_range.start);
1703
1704                let excerpt_start = excerpt_starts.next().unwrap();
1705                let mut offset = excerpt_start.bytes;
1706                let mut buffer_offset = buffer_range.start;
1707                let mut point = excerpt_start.lines;
1708                let mut buffer_point = buffer_start_point;
1709                let mut point_utf16 = excerpt_start.lines_utf16;
1710                let mut buffer_point_utf16 = buffer_start_point_utf16;
1711                for byte in buffer.bytes_in_range(buffer_range.clone()).flatten() {
1712                    let left_offset = snapshot.clip_offset(offset, Bias::Left);
1713                    let right_offset = snapshot.clip_offset(offset, Bias::Right);
1714                    let buffer_left_offset = buffer.clip_offset(buffer_offset, Bias::Left);
1715                    let buffer_right_offset = buffer.clip_offset(buffer_offset, Bias::Right);
1716                    assert_eq!(
1717                        left_offset,
1718                        excerpt_start.bytes + (buffer_left_offset - buffer_range.start),
1719                        "clip_offset({:?}, Left). buffer: {:?}, buffer offset: {:?}",
1720                        offset,
1721                        buffer_id,
1722                        buffer_offset,
1723                    );
1724                    assert_eq!(
1725                        right_offset,
1726                        excerpt_start.bytes + (buffer_right_offset - buffer_range.start),
1727                        "clip_offset({:?}, Right). buffer: {:?}, buffer offset: {:?}",
1728                        offset,
1729                        buffer_id,
1730                        buffer_offset,
1731                    );
1732
1733                    let left_point = snapshot.clip_point(point, Bias::Left);
1734                    let right_point = snapshot.clip_point(point, Bias::Right);
1735                    let buffer_left_point = buffer.clip_point(buffer_point, Bias::Left);
1736                    let buffer_right_point = buffer.clip_point(buffer_point, Bias::Right);
1737                    assert_eq!(
1738                        left_point,
1739                        excerpt_start.lines + (buffer_left_point - buffer_start_point),
1740                        "clip_point({:?}, Left). buffer: {:?}, buffer point: {:?}",
1741                        point,
1742                        buffer_id,
1743                        buffer_point,
1744                    );
1745                    assert_eq!(
1746                        right_point,
1747                        excerpt_start.lines + (buffer_right_point - buffer_start_point),
1748                        "clip_point({:?}, Right). buffer: {:?}, buffer point: {:?}",
1749                        point,
1750                        buffer_id,
1751                        buffer_point,
1752                    );
1753
1754                    let left_point_utf16 = snapshot.clip_point_utf16(point_utf16, Bias::Left);
1755                    let right_point_utf16 = snapshot.clip_point_utf16(point_utf16, Bias::Right);
1756                    let buffer_left_point_utf16 =
1757                        buffer.clip_point_utf16(buffer_point_utf16, Bias::Left);
1758                    let buffer_right_point_utf16 =
1759                        buffer.clip_point_utf16(buffer_point_utf16, Bias::Right);
1760                    assert_eq!(
1761                        left_point_utf16,
1762                        excerpt_start.lines_utf16
1763                            + (buffer_left_point_utf16 - buffer_start_point_utf16),
1764                        "clip_point_utf16({:?}, Left). buffer: {:?}, buffer point_utf16: {:?}",
1765                        point_utf16,
1766                        buffer_id,
1767                        buffer_point_utf16,
1768                    );
1769                    assert_eq!(
1770                        right_point_utf16,
1771                        excerpt_start.lines_utf16
1772                            + (buffer_right_point_utf16 - buffer_start_point_utf16),
1773                        "clip_point_utf16({:?}, Right). buffer: {:?}, buffer point_utf16: {:?}",
1774                        point_utf16,
1775                        buffer_id,
1776                        buffer_point_utf16,
1777                    );
1778
1779                    assert_eq!(
1780                        snapshot.point_to_offset(left_point),
1781                        left_offset,
1782                        "point_to_offset({:?})",
1783                        left_point,
1784                    );
1785                    assert_eq!(
1786                        snapshot.offset_to_point(left_offset),
1787                        left_point,
1788                        "offset_to_point({:?})",
1789                        left_offset,
1790                    );
1791
1792                    offset += 1;
1793                    buffer_offset += 1;
1794                    if *byte == b'\n' {
1795                        point += Point::new(1, 0);
1796                        point_utf16 += PointUtf16::new(1, 0);
1797                        buffer_point += Point::new(1, 0);
1798                        buffer_point_utf16 += PointUtf16::new(1, 0);
1799                    } else {
1800                        point += Point::new(0, 1);
1801                        point_utf16 += PointUtf16::new(0, 1);
1802                        buffer_point += Point::new(0, 1);
1803                        buffer_point_utf16 += PointUtf16::new(0, 1);
1804                    }
1805                }
1806            }
1807
1808            for (row, line) in expected_text.split('\n').enumerate() {
1809                assert_eq!(
1810                    snapshot.line_len(row as u32),
1811                    line.len() as u32,
1812                    "line_len({}).",
1813                    row
1814                );
1815            }
1816
1817            for _ in 0..10 {
1818                let end_ix = snapshot.clip_offset(rng.gen_range(0..=snapshot.len()), Bias::Right);
1819                let start_ix = snapshot.clip_offset(rng.gen_range(0..=end_ix), Bias::Left);
1820
1821                assert_eq!(
1822                    snapshot
1823                        .text_for_range(start_ix..end_ix)
1824                        .collect::<String>(),
1825                    &expected_text[start_ix..end_ix],
1826                    "incorrect text for range {:?}",
1827                    start_ix..end_ix
1828                );
1829
1830                let expected_summary = TextSummary::from(&expected_text[start_ix..end_ix]);
1831                assert_eq!(
1832                    snapshot.text_summary_for_range::<TextSummary, _>(start_ix..end_ix),
1833                    expected_summary,
1834                    "incorrect summary for range {:?}",
1835                    start_ix..end_ix
1836                );
1837            }
1838        }
1839
1840        let snapshot = list.read(cx).snapshot(cx);
1841        for (old_snapshot, subscription) in old_versions {
1842            let edits = subscription.consume().into_inner();
1843
1844            log::info!(
1845                "applying edits since old text: {:?}: {:?}",
1846                old_snapshot.text(),
1847                edits,
1848            );
1849
1850            let mut text = old_snapshot.text();
1851            for edit in edits {
1852                let new_text: String = snapshot.text_for_range(edit.new.clone()).collect();
1853                text.replace_range(edit.new.start..edit.new.start + edit.old.len(), &new_text);
1854            }
1855            assert_eq!(text.to_string(), snapshot.text());
1856        }
1857    }
1858}