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