multi_buffer.rs

   1mod anchor;
   2
   3pub use anchor::{Anchor, AnchorRangeExt};
   4use anyhow::Result;
   5use clock::ReplicaId;
   6use collections::{Bound, HashMap, HashSet};
   7use gpui::{AppContext, Entity, ModelContext, ModelHandle, Task};
   8pub use language::Completion;
   9use language::{
  10    char_kind, Buffer, BufferChunks, BufferSnapshot, CharKind, Chunk, DiagnosticEntry, Event, File,
  11    IndentSize, Language, OffsetRangeExt, Outline, OutlineItem, Selection, ToOffset as _,
  12    ToOffsetUtf16 as _, ToPoint as _, ToPointUtf16 as _, TransactionId,
  13};
  14use settings::Settings;
  15use smallvec::SmallVec;
  16use std::{
  17    borrow::Cow,
  18    cell::{Ref, RefCell},
  19    cmp, fmt, io,
  20    iter::{self, FromIterator},
  21    mem,
  22    ops::{Range, RangeBounds, Sub},
  23    str,
  24    sync::Arc,
  25    time::{Duration, Instant},
  26};
  27use sum_tree::{Bias, Cursor, SumTree};
  28use text::{
  29    locator::Locator,
  30    rope::TextDimension,
  31    subscription::{Subscription, Topic},
  32    Edit, OffsetUtf16, Point, PointUtf16, TextSummary,
  33};
  34use theme::SyntaxTheme;
  35use util::post_inc;
  36
  37const NEWLINES: &'static [u8] = &[b'\n'; u8::MAX as usize];
  38
  39pub type ExcerptId = Locator;
  40
  41pub struct MultiBuffer {
  42    snapshot: RefCell<MultiBufferSnapshot>,
  43    buffers: RefCell<HashMap<usize, BufferState>>,
  44    used_excerpt_ids: SumTree<ExcerptId>,
  45    next_excerpt_key: usize,
  46    subscriptions: Topic,
  47    singleton: bool,
  48    replica_id: ReplicaId,
  49    history: History,
  50    title: Option<String>,
  51}
  52
  53#[derive(Clone)]
  54struct History {
  55    next_transaction_id: TransactionId,
  56    undo_stack: Vec<Transaction>,
  57    redo_stack: Vec<Transaction>,
  58    transaction_depth: usize,
  59    group_interval: Duration,
  60}
  61
  62#[derive(Clone)]
  63struct Transaction {
  64    id: TransactionId,
  65    buffer_transactions: HashMap<usize, text::TransactionId>,
  66    first_edit_at: Instant,
  67    last_edit_at: Instant,
  68    suppress_grouping: bool,
  69}
  70
  71pub trait ToOffset: 'static + fmt::Debug {
  72    fn to_offset(&self, snapshot: &MultiBufferSnapshot) -> usize;
  73}
  74
  75pub trait ToOffsetUtf16: 'static + fmt::Debug {
  76    fn to_offset_utf16(&self, snapshot: &MultiBufferSnapshot) -> OffsetUtf16;
  77}
  78
  79pub trait ToPoint: 'static + fmt::Debug {
  80    fn to_point(&self, snapshot: &MultiBufferSnapshot) -> Point;
  81}
  82
  83pub trait ToPointUtf16: 'static + fmt::Debug {
  84    fn to_point_utf16(&self, snapshot: &MultiBufferSnapshot) -> PointUtf16;
  85}
  86
  87struct BufferState {
  88    buffer: ModelHandle<Buffer>,
  89    last_version: clock::Global,
  90    last_parse_count: usize,
  91    last_selections_update_count: usize,
  92    last_diagnostics_update_count: usize,
  93    last_file_update_count: usize,
  94    excerpts: Vec<ExcerptId>,
  95    _subscriptions: [gpui::Subscription; 2],
  96}
  97
  98#[derive(Clone, Default)]
  99pub struct MultiBufferSnapshot {
 100    singleton: bool,
 101    excerpts: SumTree<Excerpt>,
 102    parse_count: usize,
 103    diagnostics_update_count: usize,
 104    trailing_excerpt_update_count: usize,
 105    edit_count: usize,
 106    is_dirty: bool,
 107    has_conflict: bool,
 108}
 109
 110pub struct ExcerptBoundary {
 111    pub id: ExcerptId,
 112    pub key: usize,
 113    pub row: u32,
 114    pub buffer: BufferSnapshot,
 115    pub range: ExcerptRange<text::Anchor>,
 116    pub starts_new_buffer: bool,
 117}
 118
 119#[derive(Clone)]
 120struct Excerpt {
 121    id: ExcerptId,
 122    key: usize,
 123    buffer_id: usize,
 124    buffer: BufferSnapshot,
 125    range: ExcerptRange<text::Anchor>,
 126    max_buffer_row: u32,
 127    text_summary: TextSummary,
 128    has_trailing_newline: bool,
 129}
 130
 131#[derive(Clone, Debug, Eq, PartialEq)]
 132pub struct ExcerptRange<T> {
 133    pub context: Range<T>,
 134    pub primary: Option<Range<T>>,
 135}
 136
 137#[derive(Clone, Debug, Default)]
 138struct ExcerptSummary {
 139    excerpt_id: ExcerptId,
 140    max_buffer_row: u32,
 141    text: TextSummary,
 142}
 143
 144pub struct MultiBufferRows<'a> {
 145    buffer_row_range: Range<u32>,
 146    excerpts: Cursor<'a, Excerpt, Point>,
 147}
 148
 149pub struct MultiBufferChunks<'a> {
 150    range: Range<usize>,
 151    excerpts: Cursor<'a, Excerpt, usize>,
 152    excerpt_chunks: Option<ExcerptChunks<'a>>,
 153    language_aware: bool,
 154}
 155
 156pub struct MultiBufferBytes<'a> {
 157    range: Range<usize>,
 158    excerpts: Cursor<'a, Excerpt, usize>,
 159    excerpt_bytes: Option<ExcerptBytes<'a>>,
 160    chunk: &'a [u8],
 161}
 162
 163struct ExcerptChunks<'a> {
 164    content_chunks: BufferChunks<'a>,
 165    footer_height: usize,
 166}
 167
 168struct ExcerptBytes<'a> {
 169    content_bytes: language::rope::Bytes<'a>,
 170    footer_height: usize,
 171}
 172
 173impl MultiBuffer {
 174    pub fn new(replica_id: ReplicaId) -> Self {
 175        Self {
 176            snapshot: Default::default(),
 177            buffers: Default::default(),
 178            used_excerpt_ids: Default::default(),
 179            next_excerpt_key: Default::default(),
 180            subscriptions: Default::default(),
 181            singleton: false,
 182            replica_id,
 183            history: History {
 184                next_transaction_id: Default::default(),
 185                undo_stack: Default::default(),
 186                redo_stack: Default::default(),
 187                transaction_depth: 0,
 188                group_interval: Duration::from_millis(300),
 189            },
 190            title: Default::default(),
 191        }
 192    }
 193
 194    pub fn clone(&self, new_cx: &mut ModelContext<Self>) -> Self {
 195        let mut buffers = HashMap::default();
 196        for (buffer_id, buffer_state) in self.buffers.borrow().iter() {
 197            buffers.insert(
 198                *buffer_id,
 199                BufferState {
 200                    buffer: buffer_state.buffer.clone(),
 201                    last_version: buffer_state.last_version.clone(),
 202                    last_parse_count: buffer_state.last_parse_count,
 203                    last_selections_update_count: buffer_state.last_selections_update_count,
 204                    last_diagnostics_update_count: buffer_state.last_diagnostics_update_count,
 205                    last_file_update_count: buffer_state.last_file_update_count,
 206                    excerpts: buffer_state.excerpts.clone(),
 207                    _subscriptions: [
 208                        new_cx.observe(&buffer_state.buffer, |_, _, cx| cx.notify()),
 209                        new_cx.subscribe(&buffer_state.buffer, Self::on_buffer_event),
 210                    ],
 211                },
 212            );
 213        }
 214        Self {
 215            snapshot: RefCell::new(self.snapshot.borrow().clone()),
 216            buffers: RefCell::new(buffers),
 217            used_excerpt_ids: self.used_excerpt_ids.clone(),
 218            next_excerpt_key: self.next_excerpt_key,
 219            subscriptions: Default::default(),
 220            singleton: self.singleton,
 221            replica_id: self.replica_id,
 222            history: self.history.clone(),
 223            title: self.title.clone(),
 224        }
 225    }
 226
 227    pub fn with_title(mut self, title: String) -> Self {
 228        self.title = Some(title);
 229        self
 230    }
 231
 232    pub fn singleton(buffer: ModelHandle<Buffer>, cx: &mut ModelContext<Self>) -> Self {
 233        let mut this = Self::new(buffer.read(cx).replica_id());
 234        this.singleton = true;
 235        this.push_excerpts(
 236            buffer,
 237            [ExcerptRange {
 238                context: text::Anchor::MIN..text::Anchor::MAX,
 239                primary: None,
 240            }],
 241            cx,
 242        );
 243        this.snapshot.borrow_mut().singleton = true;
 244        this
 245    }
 246
 247    pub fn replica_id(&self) -> ReplicaId {
 248        self.replica_id
 249    }
 250
 251    pub fn snapshot(&self, cx: &AppContext) -> MultiBufferSnapshot {
 252        self.sync(cx);
 253        self.snapshot.borrow().clone()
 254    }
 255
 256    pub(crate) fn read(&self, cx: &AppContext) -> Ref<MultiBufferSnapshot> {
 257        self.sync(cx);
 258        self.snapshot.borrow()
 259    }
 260
 261    pub fn as_singleton(&self) -> Option<ModelHandle<Buffer>> {
 262        if self.singleton {
 263            return Some(
 264                self.buffers
 265                    .borrow()
 266                    .values()
 267                    .next()
 268                    .unwrap()
 269                    .buffer
 270                    .clone(),
 271            );
 272        } else {
 273            None
 274        }
 275    }
 276
 277    pub fn is_singleton(&self) -> bool {
 278        self.singleton
 279    }
 280
 281    pub fn subscribe(&mut self) -> Subscription {
 282        self.subscriptions.subscribe()
 283    }
 284
 285    pub fn is_dirty(&self, cx: &AppContext) -> bool {
 286        self.read(cx).is_dirty()
 287    }
 288
 289    pub fn has_conflict(&self, cx: &AppContext) -> bool {
 290        self.read(cx).has_conflict()
 291    }
 292
 293    pub fn len(&self, cx: &AppContext) -> usize {
 294        self.read(cx).len()
 295    }
 296
 297    pub fn symbols_containing<T: ToOffset>(
 298        &self,
 299        offset: T,
 300        theme: Option<&SyntaxTheme>,
 301        cx: &AppContext,
 302    ) -> Option<(usize, Vec<OutlineItem<Anchor>>)> {
 303        self.read(cx).symbols_containing(offset, theme)
 304    }
 305
 306    pub fn edit<I, S, T>(&mut self, edits: I, cx: &mut ModelContext<Self>)
 307    where
 308        I: IntoIterator<Item = (Range<S>, T)>,
 309        S: ToOffset,
 310        T: Into<Arc<str>>,
 311    {
 312        self.edit_internal(edits, false, cx)
 313    }
 314
 315    pub fn edit_with_autoindent<I, S, T>(&mut self, edits: I, cx: &mut ModelContext<Self>)
 316    where
 317        I: IntoIterator<Item = (Range<S>, T)>,
 318        S: ToOffset,
 319        T: Into<Arc<str>>,
 320    {
 321        self.edit_internal(edits, true, cx)
 322    }
 323
 324    pub fn edit_internal<I, S, T>(
 325        &mut self,
 326        edits: I,
 327        autoindent: bool,
 328        cx: &mut ModelContext<Self>,
 329    ) where
 330        I: IntoIterator<Item = (Range<S>, T)>,
 331        S: ToOffset,
 332        T: Into<Arc<str>>,
 333    {
 334        if self.buffers.borrow().is_empty() {
 335            return;
 336        }
 337
 338        let snapshot = self.read(cx);
 339        let edits = edits.into_iter().map(|(range, new_text)| {
 340            let mut range = range.start.to_offset(&snapshot)..range.end.to_offset(&snapshot);
 341            if range.start > range.end {
 342                mem::swap(&mut range.start, &mut range.end);
 343            }
 344            (range, new_text)
 345        });
 346
 347        if let Some(buffer) = self.as_singleton() {
 348            return buffer.update(cx, |buffer, cx| {
 349                if autoindent {
 350                    let language_name = buffer.language().map(|language| language.name());
 351                    let settings = cx.global::<Settings>();
 352                    let indent_size = if settings.hard_tabs(language_name.as_deref()) {
 353                        IndentSize::tab()
 354                    } else {
 355                        IndentSize::spaces(settings.tab_size(language_name.as_deref()).get())
 356                    };
 357                    buffer.edit_with_autoindent(edits, indent_size, cx);
 358                } else {
 359                    buffer.edit(edits, cx);
 360                }
 361            });
 362        }
 363
 364        let mut buffer_edits: HashMap<usize, Vec<(Range<usize>, Arc<str>, bool)>> =
 365            Default::default();
 366        let mut cursor = snapshot.excerpts.cursor::<usize>();
 367        for (range, new_text) in edits {
 368            let new_text: Arc<str> = new_text.into();
 369            cursor.seek(&range.start, Bias::Right, &());
 370            if cursor.item().is_none() && range.start == *cursor.start() {
 371                cursor.prev(&());
 372            }
 373            let start_excerpt = cursor.item().expect("start offset out of bounds");
 374            let start_overshoot = range.start - cursor.start();
 375            let buffer_start = start_excerpt
 376                .range
 377                .context
 378                .start
 379                .to_offset(&start_excerpt.buffer)
 380                + start_overshoot;
 381
 382            cursor.seek(&range.end, Bias::Right, &());
 383            if cursor.item().is_none() && range.end == *cursor.start() {
 384                cursor.prev(&());
 385            }
 386            let end_excerpt = cursor.item().expect("end offset out of bounds");
 387            let end_overshoot = range.end - cursor.start();
 388            let buffer_end = end_excerpt
 389                .range
 390                .context
 391                .start
 392                .to_offset(&end_excerpt.buffer)
 393                + end_overshoot;
 394
 395            if start_excerpt.id == end_excerpt.id {
 396                buffer_edits
 397                    .entry(start_excerpt.buffer_id)
 398                    .or_insert(Vec::new())
 399                    .push((buffer_start..buffer_end, new_text, true));
 400            } else {
 401                let start_excerpt_range = buffer_start
 402                    ..start_excerpt
 403                        .range
 404                        .context
 405                        .end
 406                        .to_offset(&start_excerpt.buffer);
 407                let end_excerpt_range = end_excerpt
 408                    .range
 409                    .context
 410                    .start
 411                    .to_offset(&end_excerpt.buffer)
 412                    ..buffer_end;
 413                buffer_edits
 414                    .entry(start_excerpt.buffer_id)
 415                    .or_insert(Vec::new())
 416                    .push((start_excerpt_range, new_text.clone(), true));
 417                buffer_edits
 418                    .entry(end_excerpt.buffer_id)
 419                    .or_insert(Vec::new())
 420                    .push((end_excerpt_range, new_text.clone(), false));
 421
 422                cursor.seek(&range.start, Bias::Right, &());
 423                cursor.next(&());
 424                while let Some(excerpt) = cursor.item() {
 425                    if excerpt.id == end_excerpt.id {
 426                        break;
 427                    }
 428                    buffer_edits
 429                        .entry(excerpt.buffer_id)
 430                        .or_insert(Vec::new())
 431                        .push((
 432                            excerpt.range.context.to_offset(&excerpt.buffer),
 433                            new_text.clone(),
 434                            false,
 435                        ));
 436                    cursor.next(&());
 437                }
 438            }
 439        }
 440
 441        for (buffer_id, mut edits) in buffer_edits {
 442            edits.sort_unstable_by_key(|(range, _, _)| range.start);
 443            self.buffers.borrow()[&buffer_id]
 444                .buffer
 445                .update(cx, |buffer, cx| {
 446                    let mut edits = edits.into_iter().peekable();
 447                    let mut insertions = Vec::new();
 448                    let mut deletions = Vec::new();
 449                    let empty_str: Arc<str> = "".into();
 450                    while let Some((mut range, new_text, mut is_insertion)) = edits.next() {
 451                        while let Some((next_range, _, next_is_insertion)) = edits.peek() {
 452                            if range.end >= next_range.start {
 453                                range.end = cmp::max(next_range.end, range.end);
 454
 455                                is_insertion |= *next_is_insertion;
 456                                edits.next();
 457                            } else {
 458                                break;
 459                            }
 460                        }
 461
 462                        if is_insertion {
 463                            insertions.push((
 464                                buffer.anchor_before(range.start)..buffer.anchor_before(range.end),
 465                                new_text.clone(),
 466                            ));
 467                        } else if !range.is_empty() {
 468                            deletions.push((
 469                                buffer.anchor_before(range.start)..buffer.anchor_before(range.end),
 470                                empty_str.clone(),
 471                            ));
 472                        }
 473                    }
 474                    let language_name = buffer.language().map(|l| l.name());
 475
 476                    if autoindent {
 477                        let settings = cx.global::<Settings>();
 478                        let indent_size = if settings.hard_tabs(language_name.as_deref()) {
 479                            IndentSize::tab()
 480                        } else {
 481                            IndentSize::spaces(settings.tab_size(language_name.as_deref()).get())
 482                        };
 483
 484                        buffer.edit_with_autoindent(deletions, indent_size, cx);
 485                        buffer.edit_with_autoindent(insertions, indent_size, cx);
 486                    } else {
 487                        buffer.edit(deletions, cx);
 488                        buffer.edit(insertions, cx);
 489                    }
 490                })
 491        }
 492    }
 493
 494    pub fn start_transaction(&mut self, cx: &mut ModelContext<Self>) -> Option<TransactionId> {
 495        self.start_transaction_at(Instant::now(), cx)
 496    }
 497
 498    pub(crate) fn start_transaction_at(
 499        &mut self,
 500        now: Instant,
 501        cx: &mut ModelContext<Self>,
 502    ) -> Option<TransactionId> {
 503        if let Some(buffer) = self.as_singleton() {
 504            return buffer.update(cx, |buffer, _| buffer.start_transaction_at(now));
 505        }
 506
 507        for BufferState { buffer, .. } in self.buffers.borrow().values() {
 508            buffer.update(cx, |buffer, _| buffer.start_transaction_at(now));
 509        }
 510        self.history.start_transaction(now)
 511    }
 512
 513    pub fn end_transaction(&mut self, cx: &mut ModelContext<Self>) -> Option<TransactionId> {
 514        self.end_transaction_at(Instant::now(), cx)
 515    }
 516
 517    pub(crate) fn end_transaction_at(
 518        &mut self,
 519        now: Instant,
 520        cx: &mut ModelContext<Self>,
 521    ) -> Option<TransactionId> {
 522        if let Some(buffer) = self.as_singleton() {
 523            return buffer.update(cx, |buffer, cx| buffer.end_transaction_at(now, cx));
 524        }
 525
 526        let mut buffer_transactions = HashMap::default();
 527        for BufferState { buffer, .. } in self.buffers.borrow().values() {
 528            if let Some(transaction_id) =
 529                buffer.update(cx, |buffer, cx| buffer.end_transaction_at(now, cx))
 530            {
 531                buffer_transactions.insert(buffer.id(), transaction_id);
 532            }
 533        }
 534
 535        if self.history.end_transaction(now, buffer_transactions) {
 536            let transaction_id = self.history.group().unwrap();
 537            Some(transaction_id)
 538        } else {
 539            None
 540        }
 541    }
 542
 543    pub fn finalize_last_transaction(&mut self, cx: &mut ModelContext<Self>) {
 544        self.history.finalize_last_transaction();
 545        for BufferState { buffer, .. } in self.buffers.borrow().values() {
 546            buffer.update(cx, |buffer, _| {
 547                buffer.finalize_last_transaction();
 548            });
 549        }
 550    }
 551
 552    pub fn push_transaction<'a, T>(&mut self, buffer_transactions: T)
 553    where
 554        T: IntoIterator<Item = (&'a ModelHandle<Buffer>, &'a language::Transaction)>,
 555    {
 556        self.history
 557            .push_transaction(buffer_transactions, Instant::now());
 558        self.history.finalize_last_transaction();
 559    }
 560
 561    pub fn set_active_selections(
 562        &mut self,
 563        selections: &[Selection<Anchor>],
 564        line_mode: bool,
 565        cx: &mut ModelContext<Self>,
 566    ) {
 567        let mut selections_by_buffer: HashMap<usize, Vec<Selection<text::Anchor>>> =
 568            Default::default();
 569        let snapshot = self.read(cx);
 570        let mut cursor = snapshot.excerpts.cursor::<Option<&ExcerptId>>();
 571        for selection in selections {
 572            cursor.seek(&Some(&selection.start.excerpt_id), Bias::Left, &());
 573            while let Some(excerpt) = cursor.item() {
 574                if excerpt.id > selection.end.excerpt_id {
 575                    break;
 576                }
 577
 578                let mut start = excerpt.range.context.start.clone();
 579                let mut end = excerpt.range.context.end.clone();
 580                if excerpt.id == selection.start.excerpt_id {
 581                    start = selection.start.text_anchor.clone();
 582                }
 583                if excerpt.id == selection.end.excerpt_id {
 584                    end = selection.end.text_anchor.clone();
 585                }
 586                selections_by_buffer
 587                    .entry(excerpt.buffer_id)
 588                    .or_default()
 589                    .push(Selection {
 590                        id: selection.id,
 591                        start,
 592                        end,
 593                        reversed: selection.reversed,
 594                        goal: selection.goal,
 595                    });
 596
 597                cursor.next(&());
 598            }
 599        }
 600
 601        for (buffer_id, buffer_state) in self.buffers.borrow().iter() {
 602            if !selections_by_buffer.contains_key(buffer_id) {
 603                buffer_state
 604                    .buffer
 605                    .update(cx, |buffer, cx| buffer.remove_active_selections(cx));
 606            }
 607        }
 608
 609        for (buffer_id, mut selections) in selections_by_buffer {
 610            self.buffers.borrow()[&buffer_id]
 611                .buffer
 612                .update(cx, |buffer, cx| {
 613                    selections.sort_unstable_by(|a, b| a.start.cmp(&b.start, buffer));
 614                    let mut selections = selections.into_iter().peekable();
 615                    let merged_selections = Arc::from_iter(iter::from_fn(|| {
 616                        let mut selection = selections.next()?;
 617                        while let Some(next_selection) = selections.peek() {
 618                            if selection.end.cmp(&next_selection.start, buffer).is_ge() {
 619                                let next_selection = selections.next().unwrap();
 620                                if next_selection.end.cmp(&selection.end, buffer).is_ge() {
 621                                    selection.end = next_selection.end;
 622                                }
 623                            } else {
 624                                break;
 625                            }
 626                        }
 627                        Some(selection)
 628                    }));
 629                    buffer.set_active_selections(merged_selections, line_mode, cx);
 630                });
 631        }
 632    }
 633
 634    pub fn remove_active_selections(&mut self, cx: &mut ModelContext<Self>) {
 635        for buffer in self.buffers.borrow().values() {
 636            buffer
 637                .buffer
 638                .update(cx, |buffer, cx| buffer.remove_active_selections(cx));
 639        }
 640    }
 641
 642    pub fn undo(&mut self, cx: &mut ModelContext<Self>) -> Option<TransactionId> {
 643        if let Some(buffer) = self.as_singleton() {
 644            return buffer.update(cx, |buffer, cx| buffer.undo(cx));
 645        }
 646
 647        while let Some(transaction) = self.history.pop_undo() {
 648            let mut undone = false;
 649            for (buffer_id, buffer_transaction_id) in &mut transaction.buffer_transactions {
 650                if let Some(BufferState { buffer, .. }) = self.buffers.borrow().get(&buffer_id) {
 651                    undone |= buffer.update(cx, |buffer, cx| {
 652                        let undo_to = *buffer_transaction_id;
 653                        if let Some(entry) = buffer.peek_undo_stack() {
 654                            *buffer_transaction_id = entry.transaction_id();
 655                        }
 656                        buffer.undo_to_transaction(undo_to, cx)
 657                    });
 658                }
 659            }
 660
 661            if undone {
 662                return Some(transaction.id);
 663            }
 664        }
 665
 666        None
 667    }
 668
 669    pub fn redo(&mut self, cx: &mut ModelContext<Self>) -> Option<TransactionId> {
 670        if let Some(buffer) = self.as_singleton() {
 671            return buffer.update(cx, |buffer, cx| buffer.redo(cx));
 672        }
 673
 674        while let Some(transaction) = self.history.pop_redo() {
 675            let mut redone = false;
 676            for (buffer_id, buffer_transaction_id) in &mut transaction.buffer_transactions {
 677                if let Some(BufferState { buffer, .. }) = self.buffers.borrow().get(&buffer_id) {
 678                    redone |= buffer.update(cx, |buffer, cx| {
 679                        let redo_to = *buffer_transaction_id;
 680                        if let Some(entry) = buffer.peek_redo_stack() {
 681                            *buffer_transaction_id = entry.transaction_id();
 682                        }
 683                        buffer.redo_to_transaction(redo_to, cx)
 684                    });
 685                }
 686            }
 687
 688            if redone {
 689                return Some(transaction.id);
 690            }
 691        }
 692
 693        None
 694    }
 695
 696    pub fn push_excerpts<O>(
 697        &mut self,
 698        buffer: ModelHandle<Buffer>,
 699        ranges: impl IntoIterator<Item = ExcerptRange<O>>,
 700        cx: &mut ModelContext<Self>,
 701    ) -> Vec<ExcerptId>
 702    where
 703        O: text::ToOffset,
 704    {
 705        self.insert_excerpts_after(&ExcerptId::max(), buffer, ranges, cx)
 706    }
 707
 708    pub fn push_excerpts_with_context_lines<O>(
 709        &mut self,
 710        buffer: ModelHandle<Buffer>,
 711        ranges: Vec<Range<O>>,
 712        context_line_count: u32,
 713        cx: &mut ModelContext<Self>,
 714    ) -> Vec<Range<Anchor>>
 715    where
 716        O: text::ToPoint + text::ToOffset,
 717    {
 718        let buffer_id = buffer.id();
 719        let buffer_snapshot = buffer.read(cx).snapshot();
 720        let max_point = buffer_snapshot.max_point();
 721
 722        let mut range_counts = Vec::new();
 723        let mut excerpt_ranges = Vec::new();
 724        let mut range_iter = ranges
 725            .iter()
 726            .map(|range| {
 727                range.start.to_point(&buffer_snapshot)..range.end.to_point(&buffer_snapshot)
 728            })
 729            .peekable();
 730        while let Some(range) = range_iter.next() {
 731            let excerpt_start = Point::new(range.start.row.saturating_sub(context_line_count), 0);
 732            let mut excerpt_end =
 733                Point::new(range.end.row + 1 + context_line_count, 0).min(max_point);
 734            let mut ranges_in_excerpt = 1;
 735
 736            while let Some(next_range) = range_iter.peek() {
 737                if next_range.start.row <= excerpt_end.row + context_line_count {
 738                    excerpt_end =
 739                        Point::new(next_range.end.row + 1 + context_line_count, 0).min(max_point);
 740                    ranges_in_excerpt += 1;
 741                    range_iter.next();
 742                } else {
 743                    break;
 744                }
 745            }
 746
 747            excerpt_ranges.push(ExcerptRange {
 748                context: excerpt_start..excerpt_end,
 749                primary: Some(range),
 750            });
 751            range_counts.push(ranges_in_excerpt);
 752        }
 753
 754        let excerpt_ids = self.push_excerpts(buffer, excerpt_ranges, cx);
 755
 756        let mut anchor_ranges = Vec::new();
 757        let mut ranges = ranges.into_iter();
 758        for (excerpt_id, range_count) in excerpt_ids.into_iter().zip(range_counts.into_iter()) {
 759            anchor_ranges.extend(ranges.by_ref().take(range_count).map(|range| {
 760                let start = Anchor {
 761                    buffer_id: Some(buffer_id),
 762                    excerpt_id: excerpt_id.clone(),
 763                    text_anchor: buffer_snapshot.anchor_after(range.start),
 764                };
 765                let end = Anchor {
 766                    buffer_id: Some(buffer_id),
 767                    excerpt_id: excerpt_id.clone(),
 768                    text_anchor: buffer_snapshot.anchor_after(range.end),
 769                };
 770                start..end
 771            }))
 772        }
 773        anchor_ranges
 774    }
 775
 776    pub fn insert_excerpts_after<O>(
 777        &mut self,
 778        prev_excerpt_id: &ExcerptId,
 779        buffer: ModelHandle<Buffer>,
 780        ranges: impl IntoIterator<Item = ExcerptRange<O>>,
 781        cx: &mut ModelContext<Self>,
 782    ) -> Vec<ExcerptId>
 783    where
 784        O: text::ToOffset,
 785    {
 786        assert_eq!(self.history.transaction_depth, 0);
 787        let mut ranges = ranges.into_iter().peekable();
 788        if ranges.peek().is_none() {
 789            return Default::default();
 790        }
 791
 792        self.sync(cx);
 793
 794        let buffer_id = buffer.id();
 795        let buffer_snapshot = buffer.read(cx).snapshot();
 796
 797        let mut buffers = self.buffers.borrow_mut();
 798        let buffer_state = buffers.entry(buffer_id).or_insert_with(|| BufferState {
 799            last_version: buffer_snapshot.version().clone(),
 800            last_parse_count: buffer_snapshot.parse_count(),
 801            last_selections_update_count: buffer_snapshot.selections_update_count(),
 802            last_diagnostics_update_count: buffer_snapshot.diagnostics_update_count(),
 803            last_file_update_count: buffer_snapshot.file_update_count(),
 804            excerpts: Default::default(),
 805            _subscriptions: [
 806                cx.observe(&buffer, |_, _, cx| cx.notify()),
 807                cx.subscribe(&buffer, Self::on_buffer_event),
 808            ],
 809            buffer,
 810        });
 811
 812        let mut snapshot = self.snapshot.borrow_mut();
 813        let mut cursor = snapshot.excerpts.cursor::<Option<&ExcerptId>>();
 814        let mut new_excerpts = cursor.slice(&Some(prev_excerpt_id), Bias::Right, &());
 815
 816        let edit_start = new_excerpts.summary().text.len;
 817        new_excerpts.update_last(
 818            |excerpt| {
 819                excerpt.has_trailing_newline = true;
 820            },
 821            &(),
 822        );
 823
 824        let mut used_cursor = self.used_excerpt_ids.cursor::<Locator>();
 825        used_cursor.seek(prev_excerpt_id, Bias::Right, &());
 826        let mut prev_id = if let Some(excerpt_id) = used_cursor.prev_item() {
 827            excerpt_id.clone()
 828        } else {
 829            ExcerptId::min()
 830        };
 831        let next_id = if let Some(excerpt_id) = used_cursor.item() {
 832            excerpt_id.clone()
 833        } else {
 834            ExcerptId::max()
 835        };
 836        drop(used_cursor);
 837
 838        let mut ids = Vec::new();
 839        while let Some(range) = ranges.next() {
 840            let id = ExcerptId::between(&prev_id, &next_id);
 841            if let Err(ix) = buffer_state.excerpts.binary_search(&id) {
 842                buffer_state.excerpts.insert(ix, id.clone());
 843            }
 844            let range = ExcerptRange {
 845                context: buffer_snapshot.anchor_before(&range.context.start)
 846                    ..buffer_snapshot.anchor_after(&range.context.end),
 847                primary: range.primary.map(|primary| {
 848                    buffer_snapshot.anchor_before(&primary.start)
 849                        ..buffer_snapshot.anchor_after(&primary.end)
 850                }),
 851            };
 852            let excerpt = Excerpt::new(
 853                id.clone(),
 854                post_inc(&mut self.next_excerpt_key),
 855                buffer_id,
 856                buffer_snapshot.clone(),
 857                range,
 858                ranges.peek().is_some() || cursor.item().is_some(),
 859            );
 860            new_excerpts.push(excerpt, &());
 861            prev_id = id.clone();
 862            ids.push(id);
 863        }
 864        self.used_excerpt_ids.edit(
 865            ids.iter().cloned().map(sum_tree::Edit::Insert).collect(),
 866            &(),
 867        );
 868
 869        let edit_end = new_excerpts.summary().text.len;
 870
 871        let suffix = cursor.suffix(&());
 872        let changed_trailing_excerpt = suffix.is_empty();
 873        new_excerpts.push_tree(suffix, &());
 874        drop(cursor);
 875        snapshot.excerpts = new_excerpts;
 876        if changed_trailing_excerpt {
 877            snapshot.trailing_excerpt_update_count += 1;
 878        }
 879
 880        self.subscriptions.publish_mut([Edit {
 881            old: edit_start..edit_start,
 882            new: edit_start..edit_end,
 883        }]);
 884        cx.emit(Event::Edited);
 885        cx.notify();
 886        ids
 887    }
 888
 889    pub fn clear(&mut self, cx: &mut ModelContext<Self>) {
 890        self.sync(cx);
 891        self.buffers.borrow_mut().clear();
 892        let mut snapshot = self.snapshot.borrow_mut();
 893        let prev_len = snapshot.len();
 894        snapshot.excerpts = Default::default();
 895        snapshot.trailing_excerpt_update_count += 1;
 896        snapshot.is_dirty = false;
 897        snapshot.has_conflict = false;
 898
 899        self.subscriptions.publish_mut([Edit {
 900            old: 0..prev_len,
 901            new: 0..0,
 902        }]);
 903        cx.emit(Event::Edited);
 904        cx.notify();
 905    }
 906
 907    pub fn excerpts_for_buffer(
 908        &self,
 909        buffer: &ModelHandle<Buffer>,
 910        cx: &AppContext,
 911    ) -> Vec<(ExcerptId, ExcerptRange<text::Anchor>)> {
 912        let mut excerpts = Vec::new();
 913        let snapshot = self.read(cx);
 914        let buffers = self.buffers.borrow();
 915        let mut cursor = snapshot.excerpts.cursor::<Option<&ExcerptId>>();
 916        for excerpt_id in buffers
 917            .get(&buffer.id())
 918            .map(|state| &state.excerpts)
 919            .into_iter()
 920            .flatten()
 921        {
 922            cursor.seek_forward(&Some(excerpt_id), Bias::Left, &());
 923            if let Some(excerpt) = cursor.item() {
 924                if excerpt.id == *excerpt_id {
 925                    excerpts.push((excerpt.id.clone(), excerpt.range.clone()));
 926                }
 927            }
 928        }
 929
 930        excerpts
 931    }
 932
 933    pub fn excerpt_ids(&self) -> Vec<ExcerptId> {
 934        self.buffers
 935            .borrow()
 936            .values()
 937            .flat_map(|state| state.excerpts.iter().cloned())
 938            .collect()
 939    }
 940
 941    pub fn excerpt_containing(
 942        &self,
 943        position: impl ToOffset,
 944        cx: &AppContext,
 945    ) -> Option<(ExcerptId, ModelHandle<Buffer>, Range<text::Anchor>)> {
 946        let snapshot = self.read(cx);
 947        let position = position.to_offset(&snapshot);
 948
 949        let mut cursor = snapshot.excerpts.cursor::<usize>();
 950        cursor.seek(&position, Bias::Right, &());
 951        cursor.item().map(|excerpt| {
 952            (
 953                excerpt.id.clone(),
 954                self.buffers
 955                    .borrow()
 956                    .get(&excerpt.buffer_id)
 957                    .unwrap()
 958                    .buffer
 959                    .clone(),
 960                excerpt.range.context.clone(),
 961            )
 962        })
 963    }
 964
 965    // If point is at the end of the buffer, the last excerpt is returned
 966    pub fn point_to_buffer_offset<'a, T: ToOffset>(
 967        &'a self,
 968        point: T,
 969        cx: &AppContext,
 970    ) -> Option<(ModelHandle<Buffer>, usize)> {
 971        let snapshot = self.read(cx);
 972        let offset = point.to_offset(&snapshot);
 973        let mut cursor = snapshot.excerpts.cursor::<usize>();
 974        cursor.seek(&offset, Bias::Right, &());
 975        if cursor.item().is_none() {
 976            cursor.prev(&());
 977        }
 978
 979        cursor.item().map(|excerpt| {
 980            let excerpt_start = excerpt.range.context.start.to_offset(&excerpt.buffer);
 981            let buffer_point = excerpt_start + offset - *cursor.start();
 982            let buffer = self.buffers.borrow()[&excerpt.buffer_id].buffer.clone();
 983
 984            (buffer, buffer_point)
 985        })
 986    }
 987
 988    pub fn range_to_buffer_ranges<'a, T: ToOffset>(
 989        &'a self,
 990        range: Range<T>,
 991        cx: &AppContext,
 992    ) -> Vec<(ModelHandle<Buffer>, Range<usize>)> {
 993        let snapshot = self.read(cx);
 994        let start = range.start.to_offset(&snapshot);
 995        let end = range.end.to_offset(&snapshot);
 996
 997        let mut result = Vec::new();
 998        let mut cursor = snapshot.excerpts.cursor::<usize>();
 999        cursor.seek(&start, Bias::Right, &());
1000        while let Some(excerpt) = cursor.item() {
1001            if *cursor.start() > end {
1002                break;
1003            }
1004
1005            let mut end_before_newline = cursor.end(&());
1006            if excerpt.has_trailing_newline {
1007                end_before_newline -= 1;
1008            }
1009            let excerpt_start = excerpt.range.context.start.to_offset(&excerpt.buffer);
1010            let start = excerpt_start + (cmp::max(start, *cursor.start()) - *cursor.start());
1011            let end = excerpt_start + (cmp::min(end, end_before_newline) - *cursor.start());
1012            let buffer = self.buffers.borrow()[&excerpt.buffer_id].buffer.clone();
1013            result.push((buffer, start..end));
1014            cursor.next(&());
1015        }
1016
1017        result
1018    }
1019
1020    pub fn remove_excerpts<'a>(
1021        &mut self,
1022        excerpt_ids: impl IntoIterator<Item = &'a ExcerptId>,
1023        cx: &mut ModelContext<Self>,
1024    ) {
1025        self.sync(cx);
1026        let mut buffers = self.buffers.borrow_mut();
1027        let mut snapshot = self.snapshot.borrow_mut();
1028        let mut new_excerpts = SumTree::new();
1029        let mut cursor = snapshot.excerpts.cursor::<(Option<&ExcerptId>, usize)>();
1030        let mut edits = Vec::new();
1031        let mut excerpt_ids = excerpt_ids.into_iter().peekable();
1032
1033        while let Some(mut excerpt_id) = excerpt_ids.next() {
1034            // Seek to the next excerpt to remove, preserving any preceding excerpts.
1035            new_excerpts.push_tree(cursor.slice(&Some(excerpt_id), Bias::Left, &()), &());
1036            if let Some(mut excerpt) = cursor.item() {
1037                if excerpt.id != *excerpt_id {
1038                    continue;
1039                }
1040                let mut old_start = cursor.start().1;
1041
1042                // Skip over the removed excerpt.
1043                loop {
1044                    if let Some(buffer_state) = buffers.get_mut(&excerpt.buffer_id) {
1045                        buffer_state.excerpts.retain(|id| id != excerpt_id);
1046                        if buffer_state.excerpts.is_empty() {
1047                            buffers.remove(&excerpt.buffer_id);
1048                        }
1049                    }
1050                    cursor.next(&());
1051
1052                    // Skip over any subsequent excerpts that are also removed.
1053                    if let Some(&next_excerpt_id) = excerpt_ids.peek() {
1054                        if let Some(next_excerpt) = cursor.item() {
1055                            if next_excerpt.id == *next_excerpt_id {
1056                                excerpt = next_excerpt;
1057                                excerpt_id = excerpt_ids.next().unwrap();
1058                                continue;
1059                            }
1060                        }
1061                    }
1062
1063                    break;
1064                }
1065
1066                // When removing the last excerpt, remove the trailing newline from
1067                // the previous excerpt.
1068                if cursor.item().is_none() && old_start > 0 {
1069                    old_start -= 1;
1070                    new_excerpts.update_last(|e| e.has_trailing_newline = false, &());
1071                }
1072
1073                // Push an edit for the removal of this run of excerpts.
1074                let old_end = cursor.start().1;
1075                let new_start = new_excerpts.summary().text.len;
1076                edits.push(Edit {
1077                    old: old_start..old_end,
1078                    new: new_start..new_start,
1079                });
1080            }
1081        }
1082        let suffix = cursor.suffix(&());
1083        let changed_trailing_excerpt = suffix.is_empty();
1084        new_excerpts.push_tree(suffix, &());
1085        drop(cursor);
1086        snapshot.excerpts = new_excerpts;
1087        if changed_trailing_excerpt {
1088            snapshot.trailing_excerpt_update_count += 1;
1089        }
1090
1091        self.subscriptions.publish_mut(edits);
1092        cx.emit(Event::Edited);
1093        cx.notify();
1094    }
1095
1096    pub fn text_anchor_for_position<'a, T: ToOffset>(
1097        &'a self,
1098        position: T,
1099        cx: &AppContext,
1100    ) -> Option<(ModelHandle<Buffer>, language::Anchor)> {
1101        let snapshot = self.read(cx);
1102        let anchor = snapshot.anchor_before(position);
1103        let buffer = self
1104            .buffers
1105            .borrow()
1106            .get(&anchor.buffer_id?)?
1107            .buffer
1108            .clone();
1109        Some((buffer, anchor.text_anchor))
1110    }
1111
1112    fn on_buffer_event(
1113        &mut self,
1114        _: ModelHandle<Buffer>,
1115        event: &Event,
1116        cx: &mut ModelContext<Self>,
1117    ) {
1118        cx.emit(event.clone());
1119    }
1120
1121    pub fn all_buffers(&self) -> HashSet<ModelHandle<Buffer>> {
1122        self.buffers
1123            .borrow()
1124            .values()
1125            .map(|state| state.buffer.clone())
1126            .collect()
1127    }
1128
1129    pub fn buffer(&self, buffer_id: usize) -> Option<ModelHandle<Buffer>> {
1130        self.buffers
1131            .borrow()
1132            .get(&buffer_id)
1133            .map(|state| state.buffer.clone())
1134    }
1135
1136    pub fn save(&mut self, cx: &mut ModelContext<Self>) -> Task<Result<()>> {
1137        let mut save_tasks = Vec::new();
1138        for BufferState { buffer, .. } in self.buffers.borrow().values() {
1139            save_tasks.push(buffer.update(cx, |buffer, cx| buffer.save(cx)));
1140        }
1141
1142        cx.spawn(|_, _| async move {
1143            for save in save_tasks {
1144                save.await?;
1145            }
1146            Ok(())
1147        })
1148    }
1149
1150    pub fn is_completion_trigger<T>(&self, position: T, text: &str, cx: &AppContext) -> bool
1151    where
1152        T: ToOffset,
1153    {
1154        let mut chars = text.chars();
1155        let char = if let Some(char) = chars.next() {
1156            char
1157        } else {
1158            return false;
1159        };
1160        if chars.next().is_some() {
1161            return false;
1162        }
1163
1164        if char.is_alphanumeric() || char == '_' {
1165            return true;
1166        }
1167
1168        let snapshot = self.snapshot(cx);
1169        let anchor = snapshot.anchor_before(position);
1170        anchor
1171            .buffer_id
1172            .and_then(|buffer_id| {
1173                let buffer = self.buffers.borrow().get(&buffer_id)?.buffer.clone();
1174                Some(
1175                    buffer
1176                        .read(cx)
1177                        .completion_triggers()
1178                        .iter()
1179                        .any(|string| string == text),
1180                )
1181            })
1182            .unwrap_or(false)
1183    }
1184
1185    pub fn language_at<'a, T: ToOffset>(
1186        &self,
1187        point: T,
1188        cx: &'a AppContext,
1189    ) -> Option<&'a Arc<Language>> {
1190        self.point_to_buffer_offset(point, cx)
1191            .and_then(|(buffer, _)| buffer.read(cx).language())
1192    }
1193
1194    pub fn files<'a>(&'a self, cx: &'a AppContext) -> SmallVec<[&'a dyn File; 2]> {
1195        let buffers = self.buffers.borrow();
1196        buffers
1197            .values()
1198            .filter_map(|buffer| buffer.buffer.read(cx).file())
1199            .collect()
1200    }
1201
1202    pub fn title<'a>(&'a self, cx: &'a AppContext) -> Cow<'a, str> {
1203        if let Some(title) = self.title.as_ref() {
1204            return title.into();
1205        }
1206
1207        if let Some(buffer) = self.as_singleton() {
1208            if let Some(file) = buffer.read(cx).file() {
1209                return file.file_name(cx).to_string_lossy();
1210            }
1211        }
1212
1213        "untitled".into()
1214    }
1215
1216    #[cfg(test)]
1217    pub fn is_parsing(&self, cx: &AppContext) -> bool {
1218        self.as_singleton().unwrap().read(cx).is_parsing()
1219    }
1220
1221    fn sync(&self, cx: &AppContext) {
1222        let mut snapshot = self.snapshot.borrow_mut();
1223        let mut excerpts_to_edit = Vec::new();
1224        let mut reparsed = false;
1225        let mut diagnostics_updated = false;
1226        let mut is_dirty = false;
1227        let mut has_conflict = false;
1228        let mut edited = false;
1229        let mut buffers = self.buffers.borrow_mut();
1230        for buffer_state in buffers.values_mut() {
1231            let buffer = buffer_state.buffer.read(cx);
1232            let version = buffer.version();
1233            let parse_count = buffer.parse_count();
1234            let selections_update_count = buffer.selections_update_count();
1235            let diagnostics_update_count = buffer.diagnostics_update_count();
1236            let file_update_count = buffer.file_update_count();
1237
1238            let buffer_edited = version.changed_since(&buffer_state.last_version);
1239            let buffer_reparsed = parse_count > buffer_state.last_parse_count;
1240            let buffer_selections_updated =
1241                selections_update_count > buffer_state.last_selections_update_count;
1242            let buffer_diagnostics_updated =
1243                diagnostics_update_count > buffer_state.last_diagnostics_update_count;
1244            let buffer_file_updated = file_update_count > buffer_state.last_file_update_count;
1245            if buffer_edited
1246                || buffer_reparsed
1247                || buffer_selections_updated
1248                || buffer_diagnostics_updated
1249                || buffer_file_updated
1250            {
1251                buffer_state.last_version = version;
1252                buffer_state.last_parse_count = parse_count;
1253                buffer_state.last_selections_update_count = selections_update_count;
1254                buffer_state.last_diagnostics_update_count = diagnostics_update_count;
1255                buffer_state.last_file_update_count = file_update_count;
1256                excerpts_to_edit.extend(
1257                    buffer_state
1258                        .excerpts
1259                        .iter()
1260                        .map(|excerpt_id| (excerpt_id, buffer_state.buffer.clone(), buffer_edited)),
1261                );
1262            }
1263
1264            edited |= buffer_edited;
1265            reparsed |= buffer_reparsed;
1266            diagnostics_updated |= buffer_diagnostics_updated;
1267            is_dirty |= buffer.is_dirty();
1268            has_conflict |= buffer.has_conflict();
1269        }
1270        if edited {
1271            snapshot.edit_count += 1;
1272        }
1273        if reparsed {
1274            snapshot.parse_count += 1;
1275        }
1276        if diagnostics_updated {
1277            snapshot.diagnostics_update_count += 1;
1278        }
1279        snapshot.is_dirty = is_dirty;
1280        snapshot.has_conflict = has_conflict;
1281
1282        excerpts_to_edit.sort_unstable_by_key(|(excerpt_id, _, _)| *excerpt_id);
1283
1284        let mut edits = Vec::new();
1285        let mut new_excerpts = SumTree::new();
1286        let mut cursor = snapshot.excerpts.cursor::<(Option<&ExcerptId>, usize)>();
1287
1288        for (id, buffer, buffer_edited) in excerpts_to_edit {
1289            new_excerpts.push_tree(cursor.slice(&Some(id), Bias::Left, &()), &());
1290            let old_excerpt = cursor.item().unwrap();
1291            let buffer_id = buffer.id();
1292            let buffer = buffer.read(cx);
1293
1294            let mut new_excerpt;
1295            if buffer_edited {
1296                edits.extend(
1297                    buffer
1298                        .edits_since_in_range::<usize>(
1299                            old_excerpt.buffer.version(),
1300                            old_excerpt.range.context.clone(),
1301                        )
1302                        .map(|mut edit| {
1303                            let excerpt_old_start = cursor.start().1;
1304                            let excerpt_new_start = new_excerpts.summary().text.len;
1305                            edit.old.start += excerpt_old_start;
1306                            edit.old.end += excerpt_old_start;
1307                            edit.new.start += excerpt_new_start;
1308                            edit.new.end += excerpt_new_start;
1309                            edit
1310                        }),
1311                );
1312
1313                new_excerpt = Excerpt::new(
1314                    id.clone(),
1315                    old_excerpt.key,
1316                    buffer_id,
1317                    buffer.snapshot(),
1318                    old_excerpt.range.clone(),
1319                    old_excerpt.has_trailing_newline,
1320                );
1321            } else {
1322                new_excerpt = old_excerpt.clone();
1323                new_excerpt.buffer = buffer.snapshot();
1324            }
1325
1326            new_excerpts.push(new_excerpt, &());
1327            cursor.next(&());
1328        }
1329        new_excerpts.push_tree(cursor.suffix(&()), &());
1330
1331        drop(cursor);
1332        snapshot.excerpts = new_excerpts;
1333
1334        self.subscriptions.publish(edits);
1335    }
1336}
1337
1338#[cfg(any(test, feature = "test-support"))]
1339impl MultiBuffer {
1340    pub fn build_simple(text: &str, cx: &mut gpui::MutableAppContext) -> ModelHandle<Self> {
1341        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx));
1342        cx.add_model(|cx| Self::singleton(buffer, cx))
1343    }
1344
1345    pub fn build_random(
1346        rng: &mut impl rand::Rng,
1347        cx: &mut gpui::MutableAppContext,
1348    ) -> ModelHandle<Self> {
1349        cx.add_model(|cx| {
1350            let mut multibuffer = MultiBuffer::new(0);
1351            let mutation_count = rng.gen_range(1..=5);
1352            multibuffer.randomly_edit_excerpts(rng, mutation_count, cx);
1353            multibuffer
1354        })
1355    }
1356
1357    pub fn randomly_edit(
1358        &mut self,
1359        rng: &mut impl rand::Rng,
1360        edit_count: usize,
1361        cx: &mut ModelContext<Self>,
1362    ) {
1363        use text::RandomCharIter;
1364
1365        let snapshot = self.read(cx);
1366        let mut edits: Vec<(Range<usize>, Arc<str>)> = Vec::new();
1367        let mut last_end = None;
1368        for _ in 0..edit_count {
1369            if last_end.map_or(false, |last_end| last_end >= snapshot.len()) {
1370                break;
1371            }
1372
1373            let new_start = last_end.map_or(0, |last_end| last_end + 1);
1374            let end = snapshot.clip_offset(rng.gen_range(new_start..=snapshot.len()), Bias::Right);
1375            let start = snapshot.clip_offset(rng.gen_range(new_start..=end), Bias::Right);
1376            last_end = Some(end);
1377
1378            let mut range = start..end;
1379            if rng.gen_bool(0.2) {
1380                mem::swap(&mut range.start, &mut range.end);
1381            }
1382
1383            let new_text_len = rng.gen_range(0..10);
1384            let new_text: String = RandomCharIter::new(&mut *rng).take(new_text_len).collect();
1385
1386            edits.push((range, new_text.into()));
1387        }
1388        log::info!("mutating multi-buffer with {:?}", edits);
1389        drop(snapshot);
1390
1391        self.edit(edits, cx);
1392    }
1393
1394    pub fn randomly_edit_excerpts(
1395        &mut self,
1396        rng: &mut impl rand::Rng,
1397        mutation_count: usize,
1398        cx: &mut ModelContext<Self>,
1399    ) {
1400        use rand::prelude::*;
1401        use std::env;
1402        use text::RandomCharIter;
1403
1404        let max_excerpts = env::var("MAX_EXCERPTS")
1405            .map(|i| i.parse().expect("invalid `MAX_EXCERPTS` variable"))
1406            .unwrap_or(5);
1407
1408        let mut buffers = Vec::new();
1409        for _ in 0..mutation_count {
1410            if rng.gen_bool(0.05) {
1411                log::info!("Clearing multi-buffer");
1412                self.clear(cx);
1413                continue;
1414            }
1415
1416            let excerpt_ids = self
1417                .buffers
1418                .borrow()
1419                .values()
1420                .flat_map(|b| &b.excerpts)
1421                .cloned()
1422                .collect::<Vec<_>>();
1423            if excerpt_ids.len() == 0 || (rng.gen() && excerpt_ids.len() < max_excerpts) {
1424                let buffer_handle = if rng.gen() || self.buffers.borrow().is_empty() {
1425                    let text = RandomCharIter::new(&mut *rng).take(10).collect::<String>();
1426                    buffers.push(cx.add_model(|cx| Buffer::new(0, text, cx)));
1427                    let buffer = buffers.last().unwrap();
1428                    log::info!(
1429                        "Creating new buffer {} with text: {:?}",
1430                        buffer.id(),
1431                        buffer.read(cx).text()
1432                    );
1433                    buffers.last().unwrap().clone()
1434                } else {
1435                    self.buffers
1436                        .borrow()
1437                        .values()
1438                        .choose(rng)
1439                        .unwrap()
1440                        .buffer
1441                        .clone()
1442                };
1443
1444                let buffer = buffer_handle.read(cx);
1445                let buffer_text = buffer.text();
1446                let ranges = (0..rng.gen_range(0..5))
1447                    .map(|_| {
1448                        let end_ix =
1449                            buffer.clip_offset(rng.gen_range(0..=buffer.len()), Bias::Right);
1450                        let start_ix = buffer.clip_offset(rng.gen_range(0..=end_ix), Bias::Left);
1451                        ExcerptRange {
1452                            context: start_ix..end_ix,
1453                            primary: None,
1454                        }
1455                    })
1456                    .collect::<Vec<_>>();
1457                log::info!(
1458                    "Inserting excerpts from buffer {} and ranges {:?}: {:?}",
1459                    buffer_handle.id(),
1460                    ranges,
1461                    ranges
1462                        .iter()
1463                        .map(|range| &buffer_text[range.context.clone()])
1464                        .collect::<Vec<_>>()
1465                );
1466
1467                let excerpt_id = self.push_excerpts(buffer_handle.clone(), ranges, cx);
1468                log::info!("Inserted with id: {:?}", excerpt_id);
1469            } else {
1470                let remove_count = rng.gen_range(1..=excerpt_ids.len());
1471                let mut excerpts_to_remove = excerpt_ids
1472                    .choose_multiple(rng, remove_count)
1473                    .cloned()
1474                    .collect::<Vec<_>>();
1475                excerpts_to_remove.sort();
1476                log::info!("Removing excerpts {:?}", excerpts_to_remove);
1477                self.remove_excerpts(&excerpts_to_remove, cx);
1478            }
1479        }
1480    }
1481
1482    pub fn randomly_mutate(
1483        &mut self,
1484        rng: &mut impl rand::Rng,
1485        mutation_count: usize,
1486        cx: &mut ModelContext<Self>,
1487    ) {
1488        use rand::prelude::*;
1489
1490        if rng.gen_bool(0.7) || self.singleton {
1491            let buffer = self
1492                .buffers
1493                .borrow()
1494                .values()
1495                .choose(rng)
1496                .map(|state| state.buffer.clone());
1497
1498            if rng.gen() && buffer.is_some() {
1499                buffer.unwrap().update(cx, |buffer, cx| {
1500                    if rng.gen() {
1501                        buffer.randomly_edit(rng, mutation_count, cx);
1502                    } else {
1503                        buffer.randomly_undo_redo(rng, cx);
1504                    }
1505                });
1506            } else {
1507                self.randomly_edit(rng, mutation_count, cx);
1508            }
1509        } else {
1510            self.randomly_edit_excerpts(rng, mutation_count, cx);
1511        }
1512    }
1513}
1514
1515impl Entity for MultiBuffer {
1516    type Event = language::Event;
1517}
1518
1519impl MultiBufferSnapshot {
1520    pub fn text(&self) -> String {
1521        self.chunks(0..self.len(), false)
1522            .map(|chunk| chunk.text)
1523            .collect()
1524    }
1525
1526    pub fn reversed_chars_at<'a, T: ToOffset>(
1527        &'a self,
1528        position: T,
1529    ) -> impl Iterator<Item = char> + 'a {
1530        let mut offset = position.to_offset(self);
1531        let mut cursor = self.excerpts.cursor::<usize>();
1532        cursor.seek(&offset, Bias::Left, &());
1533        let mut excerpt_chunks = cursor.item().map(|excerpt| {
1534            let end_before_footer = cursor.start() + excerpt.text_summary.len;
1535            let start = excerpt.range.context.start.to_offset(&excerpt.buffer);
1536            let end = start + (cmp::min(offset, end_before_footer) - cursor.start());
1537            excerpt.buffer.reversed_chunks_in_range(start..end)
1538        });
1539        iter::from_fn(move || {
1540            if offset == *cursor.start() {
1541                cursor.prev(&());
1542                let excerpt = cursor.item()?;
1543                excerpt_chunks = Some(
1544                    excerpt
1545                        .buffer
1546                        .reversed_chunks_in_range(excerpt.range.context.clone()),
1547                );
1548            }
1549
1550            let excerpt = cursor.item().unwrap();
1551            if offset == cursor.end(&()) && excerpt.has_trailing_newline {
1552                offset -= 1;
1553                Some("\n")
1554            } else {
1555                let chunk = excerpt_chunks.as_mut().unwrap().next().unwrap();
1556                offset -= chunk.len();
1557                Some(chunk)
1558            }
1559        })
1560        .flat_map(|c| c.chars().rev())
1561    }
1562
1563    pub fn chars_at<'a, T: ToOffset>(&'a self, position: T) -> impl Iterator<Item = char> + 'a {
1564        let offset = position.to_offset(self);
1565        self.text_for_range(offset..self.len())
1566            .flat_map(|chunk| chunk.chars())
1567    }
1568
1569    pub fn text_for_range<'a, T: ToOffset>(
1570        &'a self,
1571        range: Range<T>,
1572    ) -> impl Iterator<Item = &'a str> {
1573        self.chunks(range, false).map(|chunk| chunk.text)
1574    }
1575
1576    pub fn is_line_blank(&self, row: u32) -> bool {
1577        self.text_for_range(Point::new(row, 0)..Point::new(row, self.line_len(row)))
1578            .all(|chunk| chunk.matches(|c: char| !c.is_whitespace()).next().is_none())
1579    }
1580
1581    pub fn contains_str_at<T>(&self, position: T, needle: &str) -> bool
1582    where
1583        T: ToOffset,
1584    {
1585        let position = position.to_offset(self);
1586        position == self.clip_offset(position, Bias::Left)
1587            && self
1588                .bytes_in_range(position..self.len())
1589                .flatten()
1590                .copied()
1591                .take(needle.len())
1592                .eq(needle.bytes())
1593    }
1594
1595    pub fn surrounding_word<T: ToOffset>(&self, start: T) -> (Range<usize>, Option<CharKind>) {
1596        let mut start = start.to_offset(self);
1597        let mut end = start;
1598        let mut next_chars = self.chars_at(start).peekable();
1599        let mut prev_chars = self.reversed_chars_at(start).peekable();
1600        let word_kind = cmp::max(
1601            prev_chars.peek().copied().map(char_kind),
1602            next_chars.peek().copied().map(char_kind),
1603        );
1604
1605        for ch in prev_chars {
1606            if Some(char_kind(ch)) == word_kind && ch != '\n' {
1607                start -= ch.len_utf8();
1608            } else {
1609                break;
1610            }
1611        }
1612
1613        for ch in next_chars {
1614            if Some(char_kind(ch)) == word_kind && ch != '\n' {
1615                end += ch.len_utf8();
1616            } else {
1617                break;
1618            }
1619        }
1620
1621        (start..end, word_kind)
1622    }
1623
1624    pub fn as_singleton(&self) -> Option<(&ExcerptId, usize, &BufferSnapshot)> {
1625        if self.singleton {
1626            self.excerpts
1627                .iter()
1628                .next()
1629                .map(|e| (&e.id, e.buffer_id, &e.buffer))
1630        } else {
1631            None
1632        }
1633    }
1634
1635    pub fn len(&self) -> usize {
1636        self.excerpts.summary().text.len
1637    }
1638
1639    pub fn max_buffer_row(&self) -> u32 {
1640        self.excerpts.summary().max_buffer_row
1641    }
1642
1643    pub fn clip_offset(&self, offset: usize, bias: Bias) -> usize {
1644        if let Some((_, _, buffer)) = self.as_singleton() {
1645            return buffer.clip_offset(offset, bias);
1646        }
1647
1648        let mut cursor = self.excerpts.cursor::<usize>();
1649        cursor.seek(&offset, Bias::Right, &());
1650        let overshoot = if let Some(excerpt) = cursor.item() {
1651            let excerpt_start = excerpt.range.context.start.to_offset(&excerpt.buffer);
1652            let buffer_offset = excerpt
1653                .buffer
1654                .clip_offset(excerpt_start + (offset - cursor.start()), bias);
1655            buffer_offset.saturating_sub(excerpt_start)
1656        } else {
1657            0
1658        };
1659        cursor.start() + overshoot
1660    }
1661
1662    pub fn clip_point(&self, point: Point, bias: Bias) -> Point {
1663        if let Some((_, _, buffer)) = self.as_singleton() {
1664            return buffer.clip_point(point, bias);
1665        }
1666
1667        let mut cursor = self.excerpts.cursor::<Point>();
1668        cursor.seek(&point, Bias::Right, &());
1669        let overshoot = if let Some(excerpt) = cursor.item() {
1670            let excerpt_start = excerpt.range.context.start.to_point(&excerpt.buffer);
1671            let buffer_point = excerpt
1672                .buffer
1673                .clip_point(excerpt_start + (point - cursor.start()), bias);
1674            buffer_point.saturating_sub(excerpt_start)
1675        } else {
1676            Point::zero()
1677        };
1678        *cursor.start() + overshoot
1679    }
1680
1681    pub fn clip_point_utf16(&self, point: PointUtf16, bias: Bias) -> PointUtf16 {
1682        if let Some((_, _, buffer)) = self.as_singleton() {
1683            return buffer.clip_point_utf16(point, bias);
1684        }
1685
1686        let mut cursor = self.excerpts.cursor::<PointUtf16>();
1687        cursor.seek(&point, Bias::Right, &());
1688        let overshoot = if let Some(excerpt) = cursor.item() {
1689            let excerpt_start = excerpt
1690                .buffer
1691                .offset_to_point_utf16(excerpt.range.context.start.to_offset(&excerpt.buffer));
1692            let buffer_point = excerpt
1693                .buffer
1694                .clip_point_utf16(excerpt_start + (point - cursor.start()), bias);
1695            buffer_point.saturating_sub(excerpt_start)
1696        } else {
1697            PointUtf16::zero()
1698        };
1699        *cursor.start() + overshoot
1700    }
1701
1702    pub fn bytes_in_range<'a, T: ToOffset>(&'a self, range: Range<T>) -> MultiBufferBytes<'a> {
1703        let range = range.start.to_offset(self)..range.end.to_offset(self);
1704        let mut excerpts = self.excerpts.cursor::<usize>();
1705        excerpts.seek(&range.start, Bias::Right, &());
1706
1707        let mut chunk = &[][..];
1708        let excerpt_bytes = if let Some(excerpt) = excerpts.item() {
1709            let mut excerpt_bytes = excerpt
1710                .bytes_in_range(range.start - excerpts.start()..range.end - excerpts.start());
1711            chunk = excerpt_bytes.next().unwrap_or(&[][..]);
1712            Some(excerpt_bytes)
1713        } else {
1714            None
1715        };
1716
1717        MultiBufferBytes {
1718            range,
1719            excerpts,
1720            excerpt_bytes,
1721            chunk,
1722        }
1723    }
1724
1725    pub fn buffer_rows<'a>(&'a self, start_row: u32) -> MultiBufferRows<'a> {
1726        let mut result = MultiBufferRows {
1727            buffer_row_range: 0..0,
1728            excerpts: self.excerpts.cursor(),
1729        };
1730        result.seek(start_row);
1731        result
1732    }
1733
1734    pub fn chunks<'a, T: ToOffset>(
1735        &'a self,
1736        range: Range<T>,
1737        language_aware: bool,
1738    ) -> MultiBufferChunks<'a> {
1739        let range = range.start.to_offset(self)..range.end.to_offset(self);
1740        let mut chunks = MultiBufferChunks {
1741            range: range.clone(),
1742            excerpts: self.excerpts.cursor(),
1743            excerpt_chunks: None,
1744            language_aware,
1745        };
1746        chunks.seek(range.start);
1747        chunks
1748    }
1749
1750    pub fn offset_to_point(&self, offset: usize) -> Point {
1751        if let Some((_, _, buffer)) = self.as_singleton() {
1752            return buffer.offset_to_point(offset);
1753        }
1754
1755        let mut cursor = self.excerpts.cursor::<(usize, Point)>();
1756        cursor.seek(&offset, Bias::Right, &());
1757        if let Some(excerpt) = cursor.item() {
1758            let (start_offset, start_point) = cursor.start();
1759            let overshoot = offset - start_offset;
1760            let excerpt_start_offset = excerpt.range.context.start.to_offset(&excerpt.buffer);
1761            let excerpt_start_point = excerpt.range.context.start.to_point(&excerpt.buffer);
1762            let buffer_point = excerpt
1763                .buffer
1764                .offset_to_point(excerpt_start_offset + overshoot);
1765            *start_point + (buffer_point - excerpt_start_point)
1766        } else {
1767            self.excerpts.summary().text.lines
1768        }
1769    }
1770
1771    pub fn offset_to_point_utf16(&self, offset: usize) -> PointUtf16 {
1772        if let Some((_, _, buffer)) = self.as_singleton() {
1773            return buffer.offset_to_point_utf16(offset);
1774        }
1775
1776        let mut cursor = self.excerpts.cursor::<(usize, PointUtf16)>();
1777        cursor.seek(&offset, Bias::Right, &());
1778        if let Some(excerpt) = cursor.item() {
1779            let (start_offset, start_point) = cursor.start();
1780            let overshoot = offset - start_offset;
1781            let excerpt_start_offset = excerpt.range.context.start.to_offset(&excerpt.buffer);
1782            let excerpt_start_point = excerpt.range.context.start.to_point_utf16(&excerpt.buffer);
1783            let buffer_point = excerpt
1784                .buffer
1785                .offset_to_point_utf16(excerpt_start_offset + overshoot);
1786            *start_point + (buffer_point - excerpt_start_point)
1787        } else {
1788            self.excerpts.summary().text.lines_utf16
1789        }
1790    }
1791
1792    pub fn point_to_point_utf16(&self, point: Point) -> PointUtf16 {
1793        if let Some((_, _, buffer)) = self.as_singleton() {
1794            return buffer.point_to_point_utf16(point);
1795        }
1796
1797        let mut cursor = self.excerpts.cursor::<(Point, PointUtf16)>();
1798        cursor.seek(&point, Bias::Right, &());
1799        if let Some(excerpt) = cursor.item() {
1800            let (start_offset, start_point) = cursor.start();
1801            let overshoot = point - start_offset;
1802            let excerpt_start_point = excerpt.range.context.start.to_point(&excerpt.buffer);
1803            let excerpt_start_point_utf16 =
1804                excerpt.range.context.start.to_point_utf16(&excerpt.buffer);
1805            let buffer_point = excerpt
1806                .buffer
1807                .point_to_point_utf16(excerpt_start_point + overshoot);
1808            *start_point + (buffer_point - excerpt_start_point_utf16)
1809        } else {
1810            self.excerpts.summary().text.lines_utf16
1811        }
1812    }
1813
1814    pub fn point_to_offset(&self, point: Point) -> usize {
1815        if let Some((_, _, buffer)) = self.as_singleton() {
1816            return buffer.point_to_offset(point);
1817        }
1818
1819        let mut cursor = self.excerpts.cursor::<(Point, usize)>();
1820        cursor.seek(&point, Bias::Right, &());
1821        if let Some(excerpt) = cursor.item() {
1822            let (start_point, start_offset) = cursor.start();
1823            let overshoot = point - start_point;
1824            let excerpt_start_offset = excerpt.range.context.start.to_offset(&excerpt.buffer);
1825            let excerpt_start_point = excerpt.range.context.start.to_point(&excerpt.buffer);
1826            let buffer_offset = excerpt
1827                .buffer
1828                .point_to_offset(excerpt_start_point + overshoot);
1829            *start_offset + buffer_offset - excerpt_start_offset
1830        } else {
1831            self.excerpts.summary().text.len
1832        }
1833    }
1834
1835    pub fn offset_utf16_to_offset(&self, offset_utf16: OffsetUtf16) -> usize {
1836        if let Some((_, _, buffer)) = self.as_singleton() {
1837            return buffer.offset_utf16_to_offset(offset_utf16);
1838        }
1839
1840        let mut cursor = self.excerpts.cursor::<(OffsetUtf16, usize)>();
1841        cursor.seek(&offset_utf16, Bias::Right, &());
1842        if let Some(excerpt) = cursor.item() {
1843            let (start_offset_utf16, start_offset) = cursor.start();
1844            let overshoot = offset_utf16 - start_offset_utf16;
1845            let excerpt_start_offset = excerpt.range.context.start.to_offset(&excerpt.buffer);
1846            let excerpt_start_offset_utf16 =
1847                excerpt.buffer.offset_to_offset_utf16(excerpt_start_offset);
1848            let buffer_offset = excerpt
1849                .buffer
1850                .offset_utf16_to_offset(excerpt_start_offset_utf16 + overshoot);
1851            *start_offset + (buffer_offset - excerpt_start_offset)
1852        } else {
1853            self.excerpts.summary().text.len
1854        }
1855    }
1856
1857    pub fn offset_to_offset_utf16(&self, offset: usize) -> OffsetUtf16 {
1858        if let Some((_, _, buffer)) = self.as_singleton() {
1859            return buffer.offset_to_offset_utf16(offset);
1860        }
1861
1862        let mut cursor = self.excerpts.cursor::<(usize, OffsetUtf16)>();
1863        cursor.seek(&offset, Bias::Right, &());
1864        if let Some(excerpt) = cursor.item() {
1865            let (start_offset, start_offset_utf16) = cursor.start();
1866            let overshoot = offset - start_offset;
1867            let excerpt_start_offset_utf16 =
1868                excerpt.range.context.start.to_offset_utf16(&excerpt.buffer);
1869            let excerpt_start_offset = excerpt
1870                .buffer
1871                .offset_utf16_to_offset(excerpt_start_offset_utf16);
1872            let buffer_offset_utf16 = excerpt
1873                .buffer
1874                .offset_to_offset_utf16(excerpt_start_offset + overshoot);
1875            *start_offset_utf16 + (buffer_offset_utf16 - excerpt_start_offset_utf16)
1876        } else {
1877            OffsetUtf16(self.excerpts.summary().text.len_utf16)
1878        }
1879    }
1880
1881    pub fn point_utf16_to_offset(&self, point: PointUtf16) -> usize {
1882        if let Some((_, _, buffer)) = self.as_singleton() {
1883            return buffer.point_utf16_to_offset(point);
1884        }
1885
1886        let mut cursor = self.excerpts.cursor::<(PointUtf16, usize)>();
1887        cursor.seek(&point, Bias::Right, &());
1888        if let Some(excerpt) = cursor.item() {
1889            let (start_point, start_offset) = cursor.start();
1890            let overshoot = point - start_point;
1891            let excerpt_start_offset = excerpt.range.context.start.to_offset(&excerpt.buffer);
1892            let excerpt_start_point = excerpt
1893                .buffer
1894                .offset_to_point_utf16(excerpt.range.context.start.to_offset(&excerpt.buffer));
1895            let buffer_offset = excerpt
1896                .buffer
1897                .point_utf16_to_offset(excerpt_start_point + overshoot);
1898            *start_offset + (buffer_offset - excerpt_start_offset)
1899        } else {
1900            self.excerpts.summary().text.len
1901        }
1902    }
1903
1904    pub fn indent_size_for_line(&self, row: u32) -> IndentSize {
1905        if let Some((buffer, range)) = self.buffer_line_for_row(row) {
1906            let mut size = buffer.indent_size_for_line(range.start.row);
1907            size.len = size
1908                .len
1909                .min(range.end.column)
1910                .saturating_sub(range.start.column);
1911            size
1912        } else {
1913            IndentSize::spaces(0)
1914        }
1915    }
1916
1917    pub fn line_len(&self, row: u32) -> u32 {
1918        if let Some((_, range)) = self.buffer_line_for_row(row) {
1919            range.end.column - range.start.column
1920        } else {
1921            0
1922        }
1923    }
1924
1925    pub fn buffer_line_for_row(&self, row: u32) -> Option<(&BufferSnapshot, Range<Point>)> {
1926        let mut cursor = self.excerpts.cursor::<Point>();
1927        cursor.seek(&Point::new(row, 0), Bias::Right, &());
1928        if let Some(excerpt) = cursor.item() {
1929            let overshoot = row - cursor.start().row;
1930            let excerpt_start = excerpt.range.context.start.to_point(&excerpt.buffer);
1931            let excerpt_end = excerpt.range.context.end.to_point(&excerpt.buffer);
1932            let buffer_row = excerpt_start.row + overshoot;
1933            let line_start = Point::new(buffer_row, 0);
1934            let line_end = Point::new(buffer_row, excerpt.buffer.line_len(buffer_row));
1935            return Some((
1936                &excerpt.buffer,
1937                line_start.max(excerpt_start)..line_end.min(excerpt_end),
1938            ));
1939        }
1940        None
1941    }
1942
1943    pub fn max_point(&self) -> Point {
1944        self.text_summary().lines
1945    }
1946
1947    pub fn text_summary(&self) -> TextSummary {
1948        self.excerpts.summary().text.clone()
1949    }
1950
1951    pub fn text_summary_for_range<'a, D, O>(&'a self, range: Range<O>) -> D
1952    where
1953        D: TextDimension,
1954        O: ToOffset,
1955    {
1956        let mut summary = D::default();
1957        let mut range = range.start.to_offset(self)..range.end.to_offset(self);
1958        let mut cursor = self.excerpts.cursor::<usize>();
1959        cursor.seek(&range.start, Bias::Right, &());
1960        if let Some(excerpt) = cursor.item() {
1961            let mut end_before_newline = cursor.end(&());
1962            if excerpt.has_trailing_newline {
1963                end_before_newline -= 1;
1964            }
1965
1966            let excerpt_start = excerpt.range.context.start.to_offset(&excerpt.buffer);
1967            let start_in_excerpt = excerpt_start + (range.start - cursor.start());
1968            let end_in_excerpt =
1969                excerpt_start + (cmp::min(end_before_newline, range.end) - cursor.start());
1970            summary.add_assign(
1971                &excerpt
1972                    .buffer
1973                    .text_summary_for_range(start_in_excerpt..end_in_excerpt),
1974            );
1975
1976            if range.end > end_before_newline {
1977                summary.add_assign(&D::from_text_summary(&TextSummary::from("\n")));
1978            }
1979
1980            cursor.next(&());
1981        }
1982
1983        if range.end > *cursor.start() {
1984            summary.add_assign(&D::from_text_summary(&cursor.summary::<_, TextSummary>(
1985                &range.end,
1986                Bias::Right,
1987                &(),
1988            )));
1989            if let Some(excerpt) = cursor.item() {
1990                range.end = cmp::max(*cursor.start(), range.end);
1991
1992                let excerpt_start = excerpt.range.context.start.to_offset(&excerpt.buffer);
1993                let end_in_excerpt = excerpt_start + (range.end - cursor.start());
1994                summary.add_assign(
1995                    &excerpt
1996                        .buffer
1997                        .text_summary_for_range(excerpt_start..end_in_excerpt),
1998                );
1999            }
2000        }
2001
2002        summary
2003    }
2004
2005    pub fn summary_for_anchor<D>(&self, anchor: &Anchor) -> D
2006    where
2007        D: TextDimension + Ord + Sub<D, Output = D>,
2008    {
2009        let mut cursor = self.excerpts.cursor::<ExcerptSummary>();
2010        cursor.seek(&Some(&anchor.excerpt_id), Bias::Left, &());
2011        if cursor.item().is_none() {
2012            cursor.next(&());
2013        }
2014
2015        let mut position = D::from_text_summary(&cursor.start().text);
2016        if let Some(excerpt) = cursor.item() {
2017            if excerpt.id == anchor.excerpt_id {
2018                let excerpt_buffer_start =
2019                    excerpt.range.context.start.summary::<D>(&excerpt.buffer);
2020                let excerpt_buffer_end = excerpt.range.context.end.summary::<D>(&excerpt.buffer);
2021                let buffer_position = cmp::min(
2022                    excerpt_buffer_end,
2023                    anchor.text_anchor.summary::<D>(&excerpt.buffer),
2024                );
2025                if buffer_position > excerpt_buffer_start {
2026                    position.add_assign(&(buffer_position - excerpt_buffer_start));
2027                }
2028            }
2029        }
2030        position
2031    }
2032
2033    pub fn summaries_for_anchors<'a, D, I>(&'a self, anchors: I) -> Vec<D>
2034    where
2035        D: TextDimension + Ord + Sub<D, Output = D>,
2036        I: 'a + IntoIterator<Item = &'a Anchor>,
2037    {
2038        if let Some((_, _, buffer)) = self.as_singleton() {
2039            return buffer
2040                .summaries_for_anchors(anchors.into_iter().map(|a| &a.text_anchor))
2041                .collect();
2042        }
2043
2044        let mut anchors = anchors.into_iter().peekable();
2045        let mut cursor = self.excerpts.cursor::<ExcerptSummary>();
2046        let mut summaries = Vec::new();
2047        while let Some(anchor) = anchors.peek() {
2048            let excerpt_id = &anchor.excerpt_id;
2049            let excerpt_anchors = iter::from_fn(|| {
2050                let anchor = anchors.peek()?;
2051                if anchor.excerpt_id == *excerpt_id {
2052                    Some(&anchors.next().unwrap().text_anchor)
2053                } else {
2054                    None
2055                }
2056            });
2057
2058            cursor.seek_forward(&Some(excerpt_id), Bias::Left, &());
2059            if cursor.item().is_none() {
2060                cursor.next(&());
2061            }
2062
2063            let position = D::from_text_summary(&cursor.start().text);
2064            if let Some(excerpt) = cursor.item() {
2065                if excerpt.id == *excerpt_id {
2066                    let excerpt_buffer_start =
2067                        excerpt.range.context.start.summary::<D>(&excerpt.buffer);
2068                    let excerpt_buffer_end =
2069                        excerpt.range.context.end.summary::<D>(&excerpt.buffer);
2070                    summaries.extend(
2071                        excerpt
2072                            .buffer
2073                            .summaries_for_anchors::<D, _>(excerpt_anchors)
2074                            .map(move |summary| {
2075                                let summary = cmp::min(excerpt_buffer_end.clone(), summary);
2076                                let mut position = position.clone();
2077                                let excerpt_buffer_start = excerpt_buffer_start.clone();
2078                                if summary > excerpt_buffer_start {
2079                                    position.add_assign(&(summary - excerpt_buffer_start));
2080                                }
2081                                position
2082                            }),
2083                    );
2084                    continue;
2085                }
2086            }
2087
2088            summaries.extend(excerpt_anchors.map(|_| position.clone()));
2089        }
2090
2091        summaries
2092    }
2093
2094    pub fn refresh_anchors<'a, I>(&'a self, anchors: I) -> Vec<(usize, Anchor, bool)>
2095    where
2096        I: 'a + IntoIterator<Item = &'a Anchor>,
2097    {
2098        let mut anchors = anchors.into_iter().enumerate().peekable();
2099        let mut cursor = self.excerpts.cursor::<Option<&ExcerptId>>();
2100        let mut result = Vec::new();
2101        while let Some((_, anchor)) = anchors.peek() {
2102            let old_excerpt_id = &anchor.excerpt_id;
2103
2104            // Find the location where this anchor's excerpt should be.
2105            cursor.seek_forward(&Some(old_excerpt_id), Bias::Left, &());
2106            if cursor.item().is_none() {
2107                cursor.next(&());
2108            }
2109
2110            let next_excerpt = cursor.item();
2111            let prev_excerpt = cursor.prev_item();
2112
2113            // Process all of the anchors for this excerpt.
2114            while let Some((_, anchor)) = anchors.peek() {
2115                if anchor.excerpt_id != *old_excerpt_id {
2116                    break;
2117                }
2118                let mut kept_position = false;
2119                let (anchor_ix, anchor) = anchors.next().unwrap();
2120                let mut anchor = anchor.clone();
2121
2122                // Leave min and max anchors unchanged.
2123                if *old_excerpt_id == ExcerptId::max() || *old_excerpt_id == ExcerptId::min() {
2124                    kept_position = true;
2125                }
2126                // If the old excerpt still exists at this location, then leave
2127                // the anchor unchanged.
2128                else if next_excerpt.map_or(false, |excerpt| {
2129                    excerpt.id == *old_excerpt_id && excerpt.contains(&anchor)
2130                }) {
2131                    kept_position = true;
2132                }
2133                // If the old excerpt no longer exists at this location, then attempt to
2134                // find an equivalent position for this anchor in an adjacent excerpt.
2135                else {
2136                    for excerpt in [next_excerpt, prev_excerpt].iter().filter_map(|e| *e) {
2137                        if excerpt.contains(&anchor) {
2138                            anchor.excerpt_id = excerpt.id.clone();
2139                            kept_position = true;
2140                            break;
2141                        }
2142                    }
2143                }
2144                // If there's no adjacent excerpt that contains the anchor's position,
2145                // then report that the anchor has lost its position.
2146                if !kept_position {
2147                    anchor = if let Some(excerpt) = next_excerpt {
2148                        let mut text_anchor = excerpt
2149                            .range
2150                            .context
2151                            .start
2152                            .bias(anchor.text_anchor.bias, &excerpt.buffer);
2153                        if text_anchor
2154                            .cmp(&excerpt.range.context.end, &excerpt.buffer)
2155                            .is_gt()
2156                        {
2157                            text_anchor = excerpt.range.context.end.clone();
2158                        }
2159                        Anchor {
2160                            buffer_id: Some(excerpt.buffer_id),
2161                            excerpt_id: excerpt.id.clone(),
2162                            text_anchor,
2163                        }
2164                    } else if let Some(excerpt) = prev_excerpt {
2165                        let mut text_anchor = excerpt
2166                            .range
2167                            .context
2168                            .end
2169                            .bias(anchor.text_anchor.bias, &excerpt.buffer);
2170                        if text_anchor
2171                            .cmp(&excerpt.range.context.start, &excerpt.buffer)
2172                            .is_lt()
2173                        {
2174                            text_anchor = excerpt.range.context.start.clone();
2175                        }
2176                        Anchor {
2177                            buffer_id: Some(excerpt.buffer_id),
2178                            excerpt_id: excerpt.id.clone(),
2179                            text_anchor,
2180                        }
2181                    } else if anchor.text_anchor.bias == Bias::Left {
2182                        Anchor::min()
2183                    } else {
2184                        Anchor::max()
2185                    };
2186                }
2187
2188                result.push((anchor_ix, anchor, kept_position));
2189            }
2190        }
2191        result.sort_unstable_by(|a, b| a.1.cmp(&b.1, self));
2192        result
2193    }
2194
2195    pub fn anchor_before<T: ToOffset>(&self, position: T) -> Anchor {
2196        self.anchor_at(position, Bias::Left)
2197    }
2198
2199    pub fn anchor_after<T: ToOffset>(&self, position: T) -> Anchor {
2200        self.anchor_at(position, Bias::Right)
2201    }
2202
2203    pub fn anchor_at<T: ToOffset>(&self, position: T, mut bias: Bias) -> Anchor {
2204        let offset = position.to_offset(self);
2205        if let Some((excerpt_id, buffer_id, buffer)) = self.as_singleton() {
2206            return Anchor {
2207                buffer_id: Some(buffer_id),
2208                excerpt_id: excerpt_id.clone(),
2209                text_anchor: buffer.anchor_at(offset, bias),
2210            };
2211        }
2212
2213        let mut cursor = self.excerpts.cursor::<(usize, Option<&ExcerptId>)>();
2214        cursor.seek(&offset, Bias::Right, &());
2215        if cursor.item().is_none() && offset == cursor.start().0 && bias == Bias::Left {
2216            cursor.prev(&());
2217        }
2218        if let Some(excerpt) = cursor.item() {
2219            let mut overshoot = offset.saturating_sub(cursor.start().0);
2220            if excerpt.has_trailing_newline && offset == cursor.end(&()).0 {
2221                overshoot -= 1;
2222                bias = Bias::Right;
2223            }
2224
2225            let buffer_start = excerpt.range.context.start.to_offset(&excerpt.buffer);
2226            let text_anchor =
2227                excerpt.clip_anchor(excerpt.buffer.anchor_at(buffer_start + overshoot, bias));
2228            Anchor {
2229                buffer_id: Some(excerpt.buffer_id),
2230                excerpt_id: excerpt.id.clone(),
2231                text_anchor,
2232            }
2233        } else if offset == 0 && bias == Bias::Left {
2234            Anchor::min()
2235        } else {
2236            Anchor::max()
2237        }
2238    }
2239
2240    pub fn anchor_in_excerpt(&self, excerpt_id: ExcerptId, text_anchor: text::Anchor) -> Anchor {
2241        let mut cursor = self.excerpts.cursor::<Option<&ExcerptId>>();
2242        cursor.seek(&Some(&excerpt_id), Bias::Left, &());
2243        if let Some(excerpt) = cursor.item() {
2244            if excerpt.id == excerpt_id {
2245                let text_anchor = excerpt.clip_anchor(text_anchor);
2246                drop(cursor);
2247                return Anchor {
2248                    buffer_id: Some(excerpt.buffer_id),
2249                    excerpt_id,
2250                    text_anchor,
2251                };
2252            }
2253        }
2254        panic!("excerpt not found");
2255    }
2256
2257    pub fn can_resolve(&self, anchor: &Anchor) -> bool {
2258        if anchor.excerpt_id == ExcerptId::min() || anchor.excerpt_id == ExcerptId::max() {
2259            true
2260        } else if let Some(excerpt) = self.excerpt(&anchor.excerpt_id) {
2261            excerpt.buffer.can_resolve(&anchor.text_anchor)
2262        } else {
2263            false
2264        }
2265    }
2266
2267    pub fn excerpt_boundaries_in_range<'a, R, T>(
2268        &'a self,
2269        range: R,
2270    ) -> impl Iterator<Item = ExcerptBoundary> + 'a
2271    where
2272        R: RangeBounds<T>,
2273        T: ToOffset,
2274    {
2275        let start_offset;
2276        let start = match range.start_bound() {
2277            Bound::Included(start) => {
2278                start_offset = start.to_offset(self);
2279                Bound::Included(start_offset)
2280            }
2281            Bound::Excluded(start) => {
2282                start_offset = start.to_offset(self);
2283                Bound::Excluded(start_offset)
2284            }
2285            Bound::Unbounded => {
2286                start_offset = 0;
2287                Bound::Unbounded
2288            }
2289        };
2290        let end = match range.end_bound() {
2291            Bound::Included(end) => Bound::Included(end.to_offset(self)),
2292            Bound::Excluded(end) => Bound::Excluded(end.to_offset(self)),
2293            Bound::Unbounded => Bound::Unbounded,
2294        };
2295        let bounds = (start, end);
2296
2297        let mut cursor = self.excerpts.cursor::<(usize, Point)>();
2298        cursor.seek(&start_offset, Bias::Right, &());
2299        if cursor.item().is_none() {
2300            cursor.prev(&());
2301        }
2302        if !bounds.contains(&cursor.start().0) {
2303            cursor.next(&());
2304        }
2305
2306        let mut prev_buffer_id = cursor.prev_item().map(|excerpt| excerpt.buffer_id);
2307        std::iter::from_fn(move || {
2308            if self.singleton {
2309                None
2310            } else if bounds.contains(&cursor.start().0) {
2311                let excerpt = cursor.item()?;
2312                let starts_new_buffer = Some(excerpt.buffer_id) != prev_buffer_id;
2313                let boundary = ExcerptBoundary {
2314                    id: excerpt.id.clone(),
2315                    key: excerpt.key,
2316                    row: cursor.start().1.row,
2317                    buffer: excerpt.buffer.clone(),
2318                    range: excerpt.range.clone(),
2319                    starts_new_buffer,
2320                };
2321
2322                prev_buffer_id = Some(excerpt.buffer_id);
2323                cursor.next(&());
2324                Some(boundary)
2325            } else {
2326                None
2327            }
2328        })
2329    }
2330
2331    pub fn edit_count(&self) -> usize {
2332        self.edit_count
2333    }
2334
2335    pub fn parse_count(&self) -> usize {
2336        self.parse_count
2337    }
2338
2339    pub fn enclosing_bracket_ranges<T: ToOffset>(
2340        &self,
2341        range: Range<T>,
2342    ) -> Option<(Range<usize>, Range<usize>)> {
2343        let range = range.start.to_offset(self)..range.end.to_offset(self);
2344
2345        let mut cursor = self.excerpts.cursor::<usize>();
2346        cursor.seek(&range.start, Bias::Right, &());
2347        let start_excerpt = cursor.item();
2348
2349        cursor.seek(&range.end, Bias::Right, &());
2350        let end_excerpt = cursor.item();
2351
2352        start_excerpt
2353            .zip(end_excerpt)
2354            .and_then(|(start_excerpt, end_excerpt)| {
2355                if start_excerpt.id != end_excerpt.id {
2356                    return None;
2357                }
2358
2359                let excerpt_buffer_start = start_excerpt
2360                    .range
2361                    .context
2362                    .start
2363                    .to_offset(&start_excerpt.buffer);
2364                let excerpt_buffer_end = excerpt_buffer_start + start_excerpt.text_summary.len;
2365
2366                let start_in_buffer =
2367                    excerpt_buffer_start + range.start.saturating_sub(*cursor.start());
2368                let end_in_buffer =
2369                    excerpt_buffer_start + range.end.saturating_sub(*cursor.start());
2370                let (mut start_bracket_range, mut end_bracket_range) = start_excerpt
2371                    .buffer
2372                    .enclosing_bracket_ranges(start_in_buffer..end_in_buffer)?;
2373
2374                if start_bracket_range.start >= excerpt_buffer_start
2375                    && end_bracket_range.end <= excerpt_buffer_end
2376                {
2377                    start_bracket_range.start =
2378                        cursor.start() + (start_bracket_range.start - excerpt_buffer_start);
2379                    start_bracket_range.end =
2380                        cursor.start() + (start_bracket_range.end - excerpt_buffer_start);
2381                    end_bracket_range.start =
2382                        cursor.start() + (end_bracket_range.start - excerpt_buffer_start);
2383                    end_bracket_range.end =
2384                        cursor.start() + (end_bracket_range.end - excerpt_buffer_start);
2385                    Some((start_bracket_range, end_bracket_range))
2386                } else {
2387                    None
2388                }
2389            })
2390    }
2391
2392    pub fn diagnostics_update_count(&self) -> usize {
2393        self.diagnostics_update_count
2394    }
2395
2396    pub fn trailing_excerpt_update_count(&self) -> usize {
2397        self.trailing_excerpt_update_count
2398    }
2399
2400    pub fn language(&self) -> Option<&Arc<Language>> {
2401        self.excerpts
2402            .iter()
2403            .next()
2404            .and_then(|excerpt| excerpt.buffer.language())
2405    }
2406
2407    pub fn is_dirty(&self) -> bool {
2408        self.is_dirty
2409    }
2410
2411    pub fn has_conflict(&self) -> bool {
2412        self.has_conflict
2413    }
2414
2415    pub fn diagnostic_group<'a, O>(
2416        &'a self,
2417        group_id: usize,
2418    ) -> impl Iterator<Item = DiagnosticEntry<O>> + 'a
2419    where
2420        O: text::FromAnchor + 'a,
2421    {
2422        self.as_singleton()
2423            .into_iter()
2424            .flat_map(move |(_, _, buffer)| buffer.diagnostic_group(group_id))
2425    }
2426
2427    pub fn diagnostics_in_range<'a, T, O>(
2428        &'a self,
2429        range: Range<T>,
2430        reversed: bool,
2431    ) -> impl Iterator<Item = DiagnosticEntry<O>> + 'a
2432    where
2433        T: 'a + ToOffset,
2434        O: 'a + text::FromAnchor,
2435    {
2436        self.as_singleton()
2437            .into_iter()
2438            .flat_map(move |(_, _, buffer)| {
2439                buffer.diagnostics_in_range(
2440                    range.start.to_offset(self)..range.end.to_offset(self),
2441                    reversed,
2442                )
2443            })
2444    }
2445
2446    pub fn range_for_syntax_ancestor<T: ToOffset>(&self, range: Range<T>) -> Option<Range<usize>> {
2447        let range = range.start.to_offset(self)..range.end.to_offset(self);
2448
2449        let mut cursor = self.excerpts.cursor::<usize>();
2450        cursor.seek(&range.start, Bias::Right, &());
2451        let start_excerpt = cursor.item();
2452
2453        cursor.seek(&range.end, Bias::Right, &());
2454        let end_excerpt = cursor.item();
2455
2456        start_excerpt
2457            .zip(end_excerpt)
2458            .and_then(|(start_excerpt, end_excerpt)| {
2459                if start_excerpt.id != end_excerpt.id {
2460                    return None;
2461                }
2462
2463                let excerpt_buffer_start = start_excerpt
2464                    .range
2465                    .context
2466                    .start
2467                    .to_offset(&start_excerpt.buffer);
2468                let excerpt_buffer_end = excerpt_buffer_start + start_excerpt.text_summary.len;
2469
2470                let start_in_buffer =
2471                    excerpt_buffer_start + range.start.saturating_sub(*cursor.start());
2472                let end_in_buffer =
2473                    excerpt_buffer_start + range.end.saturating_sub(*cursor.start());
2474                let mut ancestor_buffer_range = start_excerpt
2475                    .buffer
2476                    .range_for_syntax_ancestor(start_in_buffer..end_in_buffer)?;
2477                ancestor_buffer_range.start =
2478                    cmp::max(ancestor_buffer_range.start, excerpt_buffer_start);
2479                ancestor_buffer_range.end = cmp::min(ancestor_buffer_range.end, excerpt_buffer_end);
2480
2481                let start = cursor.start() + (ancestor_buffer_range.start - excerpt_buffer_start);
2482                let end = cursor.start() + (ancestor_buffer_range.end - excerpt_buffer_start);
2483                Some(start..end)
2484            })
2485    }
2486
2487    pub fn outline(&self, theme: Option<&SyntaxTheme>) -> Option<Outline<Anchor>> {
2488        let (excerpt_id, _, buffer) = self.as_singleton()?;
2489        let outline = buffer.outline(theme)?;
2490        Some(Outline::new(
2491            outline
2492                .items
2493                .into_iter()
2494                .map(|item| OutlineItem {
2495                    depth: item.depth,
2496                    range: self.anchor_in_excerpt(excerpt_id.clone(), item.range.start)
2497                        ..self.anchor_in_excerpt(excerpt_id.clone(), item.range.end),
2498                    text: item.text,
2499                    highlight_ranges: item.highlight_ranges,
2500                    name_ranges: item.name_ranges,
2501                })
2502                .collect(),
2503        ))
2504    }
2505
2506    pub fn symbols_containing<T: ToOffset>(
2507        &self,
2508        offset: T,
2509        theme: Option<&SyntaxTheme>,
2510    ) -> Option<(usize, Vec<OutlineItem<Anchor>>)> {
2511        let anchor = self.anchor_before(offset);
2512        let excerpt_id = anchor.excerpt_id();
2513        let excerpt = self.excerpt(excerpt_id)?;
2514        Some((
2515            excerpt.buffer_id,
2516            excerpt
2517                .buffer
2518                .symbols_containing(anchor.text_anchor, theme)
2519                .into_iter()
2520                .flatten()
2521                .map(|item| OutlineItem {
2522                    depth: item.depth,
2523                    range: self.anchor_in_excerpt(excerpt_id.clone(), item.range.start)
2524                        ..self.anchor_in_excerpt(excerpt_id.clone(), item.range.end),
2525                    text: item.text,
2526                    highlight_ranges: item.highlight_ranges,
2527                    name_ranges: item.name_ranges,
2528                })
2529                .collect(),
2530        ))
2531    }
2532
2533    fn excerpt<'a>(&'a self, excerpt_id: &'a ExcerptId) -> Option<&'a Excerpt> {
2534        let mut cursor = self.excerpts.cursor::<Option<&ExcerptId>>();
2535        cursor.seek(&Some(excerpt_id), Bias::Left, &());
2536        if let Some(excerpt) = cursor.item() {
2537            if excerpt.id == *excerpt_id {
2538                return Some(excerpt);
2539            }
2540        }
2541        None
2542    }
2543
2544    pub fn remote_selections_in_range<'a>(
2545        &'a self,
2546        range: &'a Range<Anchor>,
2547    ) -> impl 'a + Iterator<Item = (ReplicaId, bool, Selection<Anchor>)> {
2548        let mut cursor = self.excerpts.cursor::<Option<&ExcerptId>>();
2549        cursor.seek(&Some(&range.start.excerpt_id), Bias::Left, &());
2550        cursor
2551            .take_while(move |excerpt| excerpt.id <= range.end.excerpt_id)
2552            .flat_map(move |excerpt| {
2553                let mut query_range =
2554                    excerpt.range.context.start.clone()..excerpt.range.context.end.clone();
2555                if excerpt.id == range.start.excerpt_id {
2556                    query_range.start = range.start.text_anchor.clone();
2557                }
2558                if excerpt.id == range.end.excerpt_id {
2559                    query_range.end = range.end.text_anchor.clone();
2560                }
2561
2562                excerpt
2563                    .buffer
2564                    .remote_selections_in_range(query_range)
2565                    .flat_map(move |(replica_id, line_mode, selections)| {
2566                        selections.map(move |selection| {
2567                            let mut start = Anchor {
2568                                buffer_id: Some(excerpt.buffer_id),
2569                                excerpt_id: excerpt.id.clone(),
2570                                text_anchor: selection.start.clone(),
2571                            };
2572                            let mut end = Anchor {
2573                                buffer_id: Some(excerpt.buffer_id),
2574                                excerpt_id: excerpt.id.clone(),
2575                                text_anchor: selection.end.clone(),
2576                            };
2577                            if range.start.cmp(&start, self).is_gt() {
2578                                start = range.start.clone();
2579                            }
2580                            if range.end.cmp(&end, self).is_lt() {
2581                                end = range.end.clone();
2582                            }
2583
2584                            (
2585                                replica_id,
2586                                line_mode,
2587                                Selection {
2588                                    id: selection.id,
2589                                    start,
2590                                    end,
2591                                    reversed: selection.reversed,
2592                                    goal: selection.goal,
2593                                },
2594                            )
2595                        })
2596                    })
2597            })
2598    }
2599}
2600
2601#[cfg(any(test, feature = "test-support"))]
2602impl MultiBufferSnapshot {
2603    pub fn random_byte_range(&self, start_offset: usize, rng: &mut impl rand::Rng) -> Range<usize> {
2604        let end = self.clip_offset(rng.gen_range(start_offset..=self.len()), Bias::Right);
2605        let start = self.clip_offset(rng.gen_range(start_offset..=end), Bias::Right);
2606        start..end
2607    }
2608}
2609
2610impl History {
2611    fn start_transaction(&mut self, now: Instant) -> Option<TransactionId> {
2612        self.transaction_depth += 1;
2613        if self.transaction_depth == 1 {
2614            let id = self.next_transaction_id.tick();
2615            self.undo_stack.push(Transaction {
2616                id,
2617                buffer_transactions: Default::default(),
2618                first_edit_at: now,
2619                last_edit_at: now,
2620                suppress_grouping: false,
2621            });
2622            Some(id)
2623        } else {
2624            None
2625        }
2626    }
2627
2628    fn end_transaction(
2629        &mut self,
2630        now: Instant,
2631        buffer_transactions: HashMap<usize, TransactionId>,
2632    ) -> bool {
2633        assert_ne!(self.transaction_depth, 0);
2634        self.transaction_depth -= 1;
2635        if self.transaction_depth == 0 {
2636            if buffer_transactions.is_empty() {
2637                self.undo_stack.pop();
2638                false
2639            } else {
2640                self.redo_stack.clear();
2641                let transaction = self.undo_stack.last_mut().unwrap();
2642                transaction.last_edit_at = now;
2643                for (buffer_id, transaction_id) in buffer_transactions {
2644                    transaction
2645                        .buffer_transactions
2646                        .entry(buffer_id)
2647                        .or_insert(transaction_id);
2648                }
2649                true
2650            }
2651        } else {
2652            false
2653        }
2654    }
2655
2656    fn push_transaction<'a, T>(&mut self, buffer_transactions: T, now: Instant)
2657    where
2658        T: IntoIterator<Item = (&'a ModelHandle<Buffer>, &'a language::Transaction)>,
2659    {
2660        assert_eq!(self.transaction_depth, 0);
2661        let transaction = Transaction {
2662            id: self.next_transaction_id.tick(),
2663            buffer_transactions: buffer_transactions
2664                .into_iter()
2665                .map(|(buffer, transaction)| (buffer.id(), transaction.id))
2666                .collect(),
2667            first_edit_at: now,
2668            last_edit_at: now,
2669            suppress_grouping: false,
2670        };
2671        if !transaction.buffer_transactions.is_empty() {
2672            self.undo_stack.push(transaction);
2673            self.redo_stack.clear();
2674        }
2675    }
2676
2677    fn finalize_last_transaction(&mut self) {
2678        if let Some(transaction) = self.undo_stack.last_mut() {
2679            transaction.suppress_grouping = true;
2680        }
2681    }
2682
2683    fn pop_undo(&mut self) -> Option<&mut Transaction> {
2684        assert_eq!(self.transaction_depth, 0);
2685        if let Some(transaction) = self.undo_stack.pop() {
2686            self.redo_stack.push(transaction);
2687            self.redo_stack.last_mut()
2688        } else {
2689            None
2690        }
2691    }
2692
2693    fn pop_redo(&mut self) -> Option<&mut Transaction> {
2694        assert_eq!(self.transaction_depth, 0);
2695        if let Some(transaction) = self.redo_stack.pop() {
2696            self.undo_stack.push(transaction);
2697            self.undo_stack.last_mut()
2698        } else {
2699            None
2700        }
2701    }
2702
2703    fn group(&mut self) -> Option<TransactionId> {
2704        let mut new_len = self.undo_stack.len();
2705        let mut transactions = self.undo_stack.iter_mut();
2706
2707        if let Some(mut transaction) = transactions.next_back() {
2708            while let Some(prev_transaction) = transactions.next_back() {
2709                if !prev_transaction.suppress_grouping
2710                    && transaction.first_edit_at - prev_transaction.last_edit_at
2711                        <= self.group_interval
2712                {
2713                    transaction = prev_transaction;
2714                    new_len -= 1;
2715                } else {
2716                    break;
2717                }
2718            }
2719        }
2720
2721        let (transactions_to_keep, transactions_to_merge) = self.undo_stack.split_at_mut(new_len);
2722        if let Some(last_transaction) = transactions_to_keep.last_mut() {
2723            if let Some(transaction) = transactions_to_merge.last() {
2724                last_transaction.last_edit_at = transaction.last_edit_at;
2725            }
2726            for to_merge in transactions_to_merge {
2727                for (buffer_id, transaction_id) in &to_merge.buffer_transactions {
2728                    last_transaction
2729                        .buffer_transactions
2730                        .entry(*buffer_id)
2731                        .or_insert(*transaction_id);
2732                }
2733            }
2734        }
2735
2736        self.undo_stack.truncate(new_len);
2737        self.undo_stack.last().map(|t| t.id)
2738    }
2739}
2740
2741impl Excerpt {
2742    fn new(
2743        id: ExcerptId,
2744        key: usize,
2745        buffer_id: usize,
2746        buffer: BufferSnapshot,
2747        range: ExcerptRange<text::Anchor>,
2748        has_trailing_newline: bool,
2749    ) -> Self {
2750        Excerpt {
2751            id,
2752            key,
2753            max_buffer_row: range.context.end.to_point(&buffer).row,
2754            text_summary: buffer
2755                .text_summary_for_range::<TextSummary, _>(range.context.to_offset(&buffer)),
2756            buffer_id,
2757            buffer,
2758            range,
2759            has_trailing_newline,
2760        }
2761    }
2762
2763    fn chunks_in_range<'a>(
2764        &'a self,
2765        range: Range<usize>,
2766        language_aware: bool,
2767    ) -> ExcerptChunks<'a> {
2768        let content_start = self.range.context.start.to_offset(&self.buffer);
2769        let chunks_start = content_start + range.start;
2770        let chunks_end = content_start + cmp::min(range.end, self.text_summary.len);
2771
2772        let footer_height = if self.has_trailing_newline
2773            && range.start <= self.text_summary.len
2774            && range.end > self.text_summary.len
2775        {
2776            1
2777        } else {
2778            0
2779        };
2780
2781        let content_chunks = self.buffer.chunks(chunks_start..chunks_end, language_aware);
2782
2783        ExcerptChunks {
2784            content_chunks,
2785            footer_height,
2786        }
2787    }
2788
2789    fn bytes_in_range(&self, range: Range<usize>) -> ExcerptBytes {
2790        let content_start = self.range.context.start.to_offset(&self.buffer);
2791        let bytes_start = content_start + range.start;
2792        let bytes_end = content_start + cmp::min(range.end, self.text_summary.len);
2793        let footer_height = if self.has_trailing_newline
2794            && range.start <= self.text_summary.len
2795            && range.end > self.text_summary.len
2796        {
2797            1
2798        } else {
2799            0
2800        };
2801        let content_bytes = self.buffer.bytes_in_range(bytes_start..bytes_end);
2802
2803        ExcerptBytes {
2804            content_bytes,
2805            footer_height,
2806        }
2807    }
2808
2809    fn clip_anchor(&self, text_anchor: text::Anchor) -> text::Anchor {
2810        if text_anchor
2811            .cmp(&self.range.context.start, &self.buffer)
2812            .is_lt()
2813        {
2814            self.range.context.start.clone()
2815        } else if text_anchor
2816            .cmp(&self.range.context.end, &self.buffer)
2817            .is_gt()
2818        {
2819            self.range.context.end.clone()
2820        } else {
2821            text_anchor
2822        }
2823    }
2824
2825    fn contains(&self, anchor: &Anchor) -> bool {
2826        Some(self.buffer_id) == anchor.buffer_id
2827            && self
2828                .range
2829                .context
2830                .start
2831                .cmp(&anchor.text_anchor, &self.buffer)
2832                .is_le()
2833            && self
2834                .range
2835                .context
2836                .end
2837                .cmp(&anchor.text_anchor, &self.buffer)
2838                .is_ge()
2839    }
2840}
2841
2842impl fmt::Debug for Excerpt {
2843    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2844        f.debug_struct("Excerpt")
2845            .field("id", &self.id)
2846            .field("buffer_id", &self.buffer_id)
2847            .field("range", &self.range)
2848            .field("text_summary", &self.text_summary)
2849            .field("has_trailing_newline", &self.has_trailing_newline)
2850            .finish()
2851    }
2852}
2853
2854impl sum_tree::Item for Excerpt {
2855    type Summary = ExcerptSummary;
2856
2857    fn summary(&self) -> Self::Summary {
2858        let mut text = self.text_summary.clone();
2859        if self.has_trailing_newline {
2860            text += TextSummary::from("\n");
2861        }
2862        ExcerptSummary {
2863            excerpt_id: self.id.clone(),
2864            max_buffer_row: self.max_buffer_row,
2865            text,
2866        }
2867    }
2868}
2869
2870impl sum_tree::Summary for ExcerptSummary {
2871    type Context = ();
2872
2873    fn add_summary(&mut self, summary: &Self, _: &()) {
2874        debug_assert!(summary.excerpt_id > self.excerpt_id);
2875        self.excerpt_id = summary.excerpt_id.clone();
2876        self.text.add_summary(&summary.text, &());
2877        self.max_buffer_row = cmp::max(self.max_buffer_row, summary.max_buffer_row);
2878    }
2879}
2880
2881impl<'a> sum_tree::Dimension<'a, ExcerptSummary> for TextSummary {
2882    fn add_summary(&mut self, summary: &'a ExcerptSummary, _: &()) {
2883        *self += &summary.text;
2884    }
2885}
2886
2887impl<'a> sum_tree::Dimension<'a, ExcerptSummary> for usize {
2888    fn add_summary(&mut self, summary: &'a ExcerptSummary, _: &()) {
2889        *self += summary.text.len;
2890    }
2891}
2892
2893impl<'a> sum_tree::SeekTarget<'a, ExcerptSummary, ExcerptSummary> for usize {
2894    fn cmp(&self, cursor_location: &ExcerptSummary, _: &()) -> cmp::Ordering {
2895        Ord::cmp(self, &cursor_location.text.len)
2896    }
2897}
2898
2899impl<'a> sum_tree::SeekTarget<'a, ExcerptSummary, ExcerptSummary> for Option<&'a ExcerptId> {
2900    fn cmp(&self, cursor_location: &ExcerptSummary, _: &()) -> cmp::Ordering {
2901        Ord::cmp(self, &Some(&cursor_location.excerpt_id))
2902    }
2903}
2904
2905impl<'a> sum_tree::Dimension<'a, ExcerptSummary> for OffsetUtf16 {
2906    fn add_summary(&mut self, summary: &'a ExcerptSummary, _: &()) {
2907        self.0 += summary.text.len_utf16;
2908    }
2909}
2910
2911impl<'a> sum_tree::Dimension<'a, ExcerptSummary> for Point {
2912    fn add_summary(&mut self, summary: &'a ExcerptSummary, _: &()) {
2913        *self += summary.text.lines;
2914    }
2915}
2916
2917impl<'a> sum_tree::Dimension<'a, ExcerptSummary> for PointUtf16 {
2918    fn add_summary(&mut self, summary: &'a ExcerptSummary, _: &()) {
2919        *self += summary.text.lines_utf16
2920    }
2921}
2922
2923impl<'a> sum_tree::Dimension<'a, ExcerptSummary> for Option<&'a ExcerptId> {
2924    fn add_summary(&mut self, summary: &'a ExcerptSummary, _: &()) {
2925        *self = Some(&summary.excerpt_id);
2926    }
2927}
2928
2929impl<'a> MultiBufferRows<'a> {
2930    pub fn seek(&mut self, row: u32) {
2931        self.buffer_row_range = 0..0;
2932
2933        self.excerpts
2934            .seek_forward(&Point::new(row, 0), Bias::Right, &());
2935        if self.excerpts.item().is_none() {
2936            self.excerpts.prev(&());
2937
2938            if self.excerpts.item().is_none() && row == 0 {
2939                self.buffer_row_range = 0..1;
2940                return;
2941            }
2942        }
2943
2944        if let Some(excerpt) = self.excerpts.item() {
2945            let overshoot = row - self.excerpts.start().row;
2946            let excerpt_start = excerpt.range.context.start.to_point(&excerpt.buffer).row;
2947            self.buffer_row_range.start = excerpt_start + overshoot;
2948            self.buffer_row_range.end = excerpt_start + excerpt.text_summary.lines.row + 1;
2949        }
2950    }
2951}
2952
2953impl<'a> Iterator for MultiBufferRows<'a> {
2954    type Item = Option<u32>;
2955
2956    fn next(&mut self) -> Option<Self::Item> {
2957        loop {
2958            if !self.buffer_row_range.is_empty() {
2959                let row = Some(self.buffer_row_range.start);
2960                self.buffer_row_range.start += 1;
2961                return Some(row);
2962            }
2963            self.excerpts.item()?;
2964            self.excerpts.next(&());
2965            let excerpt = self.excerpts.item()?;
2966            self.buffer_row_range.start = excerpt.range.context.start.to_point(&excerpt.buffer).row;
2967            self.buffer_row_range.end =
2968                self.buffer_row_range.start + excerpt.text_summary.lines.row + 1;
2969        }
2970    }
2971}
2972
2973impl<'a> MultiBufferChunks<'a> {
2974    pub fn offset(&self) -> usize {
2975        self.range.start
2976    }
2977
2978    pub fn seek(&mut self, offset: usize) {
2979        self.range.start = offset;
2980        self.excerpts.seek(&offset, Bias::Right, &());
2981        if let Some(excerpt) = self.excerpts.item() {
2982            self.excerpt_chunks = Some(excerpt.chunks_in_range(
2983                self.range.start - self.excerpts.start()..self.range.end - self.excerpts.start(),
2984                self.language_aware,
2985            ));
2986        } else {
2987            self.excerpt_chunks = None;
2988        }
2989    }
2990}
2991
2992impl<'a> Iterator for MultiBufferChunks<'a> {
2993    type Item = Chunk<'a>;
2994
2995    fn next(&mut self) -> Option<Self::Item> {
2996        if self.range.is_empty() {
2997            None
2998        } else if let Some(chunk) = self.excerpt_chunks.as_mut()?.next() {
2999            self.range.start += chunk.text.len();
3000            Some(chunk)
3001        } else {
3002            self.excerpts.next(&());
3003            let excerpt = self.excerpts.item()?;
3004            self.excerpt_chunks = Some(excerpt.chunks_in_range(
3005                0..self.range.end - self.excerpts.start(),
3006                self.language_aware,
3007            ));
3008            self.next()
3009        }
3010    }
3011}
3012
3013impl<'a> MultiBufferBytes<'a> {
3014    fn consume(&mut self, len: usize) {
3015        self.range.start += len;
3016        self.chunk = &self.chunk[len..];
3017
3018        if !self.range.is_empty() && self.chunk.is_empty() {
3019            if let Some(chunk) = self.excerpt_bytes.as_mut().and_then(|bytes| bytes.next()) {
3020                self.chunk = chunk;
3021            } else {
3022                self.excerpts.next(&());
3023                if let Some(excerpt) = self.excerpts.item() {
3024                    let mut excerpt_bytes =
3025                        excerpt.bytes_in_range(0..self.range.end - self.excerpts.start());
3026                    self.chunk = excerpt_bytes.next().unwrap();
3027                    self.excerpt_bytes = Some(excerpt_bytes);
3028                }
3029            }
3030        }
3031    }
3032}
3033
3034impl<'a> Iterator for MultiBufferBytes<'a> {
3035    type Item = &'a [u8];
3036
3037    fn next(&mut self) -> Option<Self::Item> {
3038        let chunk = self.chunk;
3039        if chunk.is_empty() {
3040            None
3041        } else {
3042            self.consume(chunk.len());
3043            Some(chunk)
3044        }
3045    }
3046}
3047
3048impl<'a> io::Read for MultiBufferBytes<'a> {
3049    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
3050        let len = cmp::min(buf.len(), self.chunk.len());
3051        buf[..len].copy_from_slice(&self.chunk[..len]);
3052        if len > 0 {
3053            self.consume(len);
3054        }
3055        Ok(len)
3056    }
3057}
3058
3059impl<'a> Iterator for ExcerptBytes<'a> {
3060    type Item = &'a [u8];
3061
3062    fn next(&mut self) -> Option<Self::Item> {
3063        if let Some(chunk) = self.content_bytes.next() {
3064            if !chunk.is_empty() {
3065                return Some(chunk);
3066            }
3067        }
3068
3069        if self.footer_height > 0 {
3070            let result = &NEWLINES[..self.footer_height];
3071            self.footer_height = 0;
3072            return Some(result);
3073        }
3074
3075        None
3076    }
3077}
3078
3079impl<'a> Iterator for ExcerptChunks<'a> {
3080    type Item = Chunk<'a>;
3081
3082    fn next(&mut self) -> Option<Self::Item> {
3083        if let Some(chunk) = self.content_chunks.next() {
3084            return Some(chunk);
3085        }
3086
3087        if self.footer_height > 0 {
3088            let text = unsafe { str::from_utf8_unchecked(&NEWLINES[..self.footer_height]) };
3089            self.footer_height = 0;
3090            return Some(Chunk {
3091                text,
3092                ..Default::default()
3093            });
3094        }
3095
3096        None
3097    }
3098}
3099
3100impl ToOffset for Point {
3101    fn to_offset<'a>(&self, snapshot: &MultiBufferSnapshot) -> usize {
3102        snapshot.point_to_offset(*self)
3103    }
3104}
3105
3106impl ToOffset for PointUtf16 {
3107    fn to_offset<'a>(&self, snapshot: &MultiBufferSnapshot) -> usize {
3108        snapshot.point_utf16_to_offset(*self)
3109    }
3110}
3111
3112impl ToOffset for usize {
3113    fn to_offset<'a>(&self, snapshot: &MultiBufferSnapshot) -> usize {
3114        assert!(*self <= snapshot.len(), "offset is out of range");
3115        *self
3116    }
3117}
3118
3119impl ToOffset for OffsetUtf16 {
3120    fn to_offset<'a>(&self, snapshot: &MultiBufferSnapshot) -> usize {
3121        snapshot.offset_utf16_to_offset(*self)
3122    }
3123}
3124
3125impl ToOffsetUtf16 for OffsetUtf16 {
3126    fn to_offset_utf16(&self, _snapshot: &MultiBufferSnapshot) -> OffsetUtf16 {
3127        *self
3128    }
3129}
3130
3131impl ToOffsetUtf16 for usize {
3132    fn to_offset_utf16(&self, snapshot: &MultiBufferSnapshot) -> OffsetUtf16 {
3133        snapshot.offset_to_offset_utf16(*self)
3134    }
3135}
3136
3137impl ToPoint for usize {
3138    fn to_point<'a>(&self, snapshot: &MultiBufferSnapshot) -> Point {
3139        snapshot.offset_to_point(*self)
3140    }
3141}
3142
3143impl ToPoint for Point {
3144    fn to_point<'a>(&self, _: &MultiBufferSnapshot) -> Point {
3145        *self
3146    }
3147}
3148
3149impl ToPointUtf16 for usize {
3150    fn to_point_utf16<'a>(&self, snapshot: &MultiBufferSnapshot) -> PointUtf16 {
3151        snapshot.offset_to_point_utf16(*self)
3152    }
3153}
3154
3155impl ToPointUtf16 for Point {
3156    fn to_point_utf16<'a>(&self, snapshot: &MultiBufferSnapshot) -> PointUtf16 {
3157        snapshot.point_to_point_utf16(*self)
3158    }
3159}
3160
3161impl ToPointUtf16 for PointUtf16 {
3162    fn to_point_utf16<'a>(&self, _: &MultiBufferSnapshot) -> PointUtf16 {
3163        *self
3164    }
3165}
3166
3167#[cfg(test)]
3168mod tests {
3169    use super::*;
3170    use gpui::MutableAppContext;
3171    use language::{Buffer, Rope};
3172    use rand::prelude::*;
3173    use std::{env, rc::Rc};
3174    use text::{Point, RandomCharIter};
3175    use util::test::sample_text;
3176
3177    #[gpui::test]
3178    fn test_singleton_multibuffer(cx: &mut MutableAppContext) {
3179        let buffer = cx.add_model(|cx| Buffer::new(0, sample_text(6, 6, 'a'), cx));
3180        let multibuffer = cx.add_model(|cx| MultiBuffer::singleton(buffer.clone(), cx));
3181
3182        let snapshot = multibuffer.read(cx).snapshot(cx);
3183        assert_eq!(snapshot.text(), buffer.read(cx).text());
3184
3185        assert_eq!(
3186            snapshot.buffer_rows(0).collect::<Vec<_>>(),
3187            (0..buffer.read(cx).row_count())
3188                .map(Some)
3189                .collect::<Vec<_>>()
3190        );
3191
3192        buffer.update(cx, |buffer, cx| buffer.edit([(1..3, "XXX\n")], cx));
3193        let snapshot = multibuffer.read(cx).snapshot(cx);
3194
3195        assert_eq!(snapshot.text(), buffer.read(cx).text());
3196        assert_eq!(
3197            snapshot.buffer_rows(0).collect::<Vec<_>>(),
3198            (0..buffer.read(cx).row_count())
3199                .map(Some)
3200                .collect::<Vec<_>>()
3201        );
3202    }
3203
3204    #[gpui::test]
3205    fn test_remote_multibuffer(cx: &mut MutableAppContext) {
3206        let host_buffer = cx.add_model(|cx| Buffer::new(0, "a", cx));
3207        let guest_buffer = cx.add_model(|cx| {
3208            let message = host_buffer.read(cx).to_proto();
3209            Buffer::from_proto(1, message, None, cx).unwrap()
3210        });
3211        let multibuffer = cx.add_model(|cx| MultiBuffer::singleton(guest_buffer.clone(), cx));
3212        let snapshot = multibuffer.read(cx).snapshot(cx);
3213        assert_eq!(snapshot.text(), "a");
3214
3215        guest_buffer.update(cx, |buffer, cx| buffer.edit([(1..1, "b")], cx));
3216        let snapshot = multibuffer.read(cx).snapshot(cx);
3217        assert_eq!(snapshot.text(), "ab");
3218
3219        guest_buffer.update(cx, |buffer, cx| buffer.edit([(2..2, "c")], cx));
3220        let snapshot = multibuffer.read(cx).snapshot(cx);
3221        assert_eq!(snapshot.text(), "abc");
3222    }
3223
3224    #[gpui::test]
3225    fn test_excerpt_buffer(cx: &mut MutableAppContext) {
3226        let buffer_1 = cx.add_model(|cx| Buffer::new(0, sample_text(6, 6, 'a'), cx));
3227        let buffer_2 = cx.add_model(|cx| Buffer::new(0, sample_text(6, 6, 'g'), cx));
3228        let multibuffer = cx.add_model(|_| MultiBuffer::new(0));
3229
3230        let events = Rc::new(RefCell::new(Vec::<Event>::new()));
3231        multibuffer.update(cx, |_, cx| {
3232            let events = events.clone();
3233            cx.subscribe(&multibuffer, move |_, _, event, _| {
3234                events.borrow_mut().push(event.clone())
3235            })
3236            .detach();
3237        });
3238
3239        let subscription = multibuffer.update(cx, |multibuffer, cx| {
3240            let subscription = multibuffer.subscribe();
3241            multibuffer.push_excerpts(
3242                buffer_1.clone(),
3243                [ExcerptRange {
3244                    context: Point::new(1, 2)..Point::new(2, 5),
3245                    primary: None,
3246                }],
3247                cx,
3248            );
3249            assert_eq!(
3250                subscription.consume().into_inner(),
3251                [Edit {
3252                    old: 0..0,
3253                    new: 0..10
3254                }]
3255            );
3256
3257            multibuffer.push_excerpts(
3258                buffer_1.clone(),
3259                [ExcerptRange {
3260                    context: Point::new(3, 3)..Point::new(4, 4),
3261                    primary: None,
3262                }],
3263                cx,
3264            );
3265            multibuffer.push_excerpts(
3266                buffer_2.clone(),
3267                [ExcerptRange {
3268                    context: Point::new(3, 1)..Point::new(3, 3),
3269                    primary: None,
3270                }],
3271                cx,
3272            );
3273            assert_eq!(
3274                subscription.consume().into_inner(),
3275                [Edit {
3276                    old: 10..10,
3277                    new: 10..22
3278                }]
3279            );
3280
3281            subscription
3282        });
3283
3284        // Adding excerpts emits an edited event.
3285        assert_eq!(
3286            events.borrow().as_slice(),
3287            &[Event::Edited, Event::Edited, Event::Edited]
3288        );
3289
3290        let snapshot = multibuffer.read(cx).snapshot(cx);
3291        assert_eq!(
3292            snapshot.text(),
3293            concat!(
3294                "bbbb\n",  // Preserve newlines
3295                "ccccc\n", //
3296                "ddd\n",   //
3297                "eeee\n",  //
3298                "jj"       //
3299            )
3300        );
3301        assert_eq!(
3302            snapshot.buffer_rows(0).collect::<Vec<_>>(),
3303            [Some(1), Some(2), Some(3), Some(4), Some(3)]
3304        );
3305        assert_eq!(
3306            snapshot.buffer_rows(2).collect::<Vec<_>>(),
3307            [Some(3), Some(4), Some(3)]
3308        );
3309        assert_eq!(snapshot.buffer_rows(4).collect::<Vec<_>>(), [Some(3)]);
3310        assert_eq!(snapshot.buffer_rows(5).collect::<Vec<_>>(), []);
3311
3312        assert_eq!(
3313            boundaries_in_range(Point::new(0, 0)..Point::new(4, 2), &snapshot),
3314            &[
3315                (0, "bbbb\nccccc".to_string(), true),
3316                (2, "ddd\neeee".to_string(), false),
3317                (4, "jj".to_string(), true),
3318            ]
3319        );
3320        assert_eq!(
3321            boundaries_in_range(Point::new(0, 0)..Point::new(2, 0), &snapshot),
3322            &[(0, "bbbb\nccccc".to_string(), true)]
3323        );
3324        assert_eq!(
3325            boundaries_in_range(Point::new(1, 0)..Point::new(1, 5), &snapshot),
3326            &[]
3327        );
3328        assert_eq!(
3329            boundaries_in_range(Point::new(1, 0)..Point::new(2, 0), &snapshot),
3330            &[]
3331        );
3332        assert_eq!(
3333            boundaries_in_range(Point::new(1, 0)..Point::new(4, 0), &snapshot),
3334            &[(2, "ddd\neeee".to_string(), false)]
3335        );
3336        assert_eq!(
3337            boundaries_in_range(Point::new(1, 0)..Point::new(4, 0), &snapshot),
3338            &[(2, "ddd\neeee".to_string(), false)]
3339        );
3340        assert_eq!(
3341            boundaries_in_range(Point::new(2, 0)..Point::new(3, 0), &snapshot),
3342            &[(2, "ddd\neeee".to_string(), false)]
3343        );
3344        assert_eq!(
3345            boundaries_in_range(Point::new(4, 0)..Point::new(4, 2), &snapshot),
3346            &[(4, "jj".to_string(), true)]
3347        );
3348        assert_eq!(
3349            boundaries_in_range(Point::new(4, 2)..Point::new(4, 2), &snapshot),
3350            &[]
3351        );
3352
3353        buffer_1.update(cx, |buffer, cx| {
3354            let text = "\n";
3355            buffer.edit(
3356                [
3357                    (Point::new(0, 0)..Point::new(0, 0), text),
3358                    (Point::new(2, 1)..Point::new(2, 3), text),
3359                ],
3360                cx,
3361            );
3362        });
3363
3364        let snapshot = multibuffer.read(cx).snapshot(cx);
3365        assert_eq!(
3366            snapshot.text(),
3367            concat!(
3368                "bbbb\n", // Preserve newlines
3369                "c\n",    //
3370                "cc\n",   //
3371                "ddd\n",  //
3372                "eeee\n", //
3373                "jj"      //
3374            )
3375        );
3376
3377        assert_eq!(
3378            subscription.consume().into_inner(),
3379            [Edit {
3380                old: 6..8,
3381                new: 6..7
3382            }]
3383        );
3384
3385        let snapshot = multibuffer.read(cx).snapshot(cx);
3386        assert_eq!(
3387            snapshot.clip_point(Point::new(0, 5), Bias::Left),
3388            Point::new(0, 4)
3389        );
3390        assert_eq!(
3391            snapshot.clip_point(Point::new(0, 5), Bias::Right),
3392            Point::new(0, 4)
3393        );
3394        assert_eq!(
3395            snapshot.clip_point(Point::new(5, 1), Bias::Right),
3396            Point::new(5, 1)
3397        );
3398        assert_eq!(
3399            snapshot.clip_point(Point::new(5, 2), Bias::Right),
3400            Point::new(5, 2)
3401        );
3402        assert_eq!(
3403            snapshot.clip_point(Point::new(5, 3), Bias::Right),
3404            Point::new(5, 2)
3405        );
3406
3407        let snapshot = multibuffer.update(cx, |multibuffer, cx| {
3408            let (buffer_2_excerpt_id, _) =
3409                multibuffer.excerpts_for_buffer(&buffer_2, cx)[0].clone();
3410            multibuffer.remove_excerpts(&[buffer_2_excerpt_id], cx);
3411            multibuffer.snapshot(cx)
3412        });
3413
3414        assert_eq!(
3415            snapshot.text(),
3416            concat!(
3417                "bbbb\n", // Preserve newlines
3418                "c\n",    //
3419                "cc\n",   //
3420                "ddd\n",  //
3421                "eeee",   //
3422            )
3423        );
3424
3425        fn boundaries_in_range(
3426            range: Range<Point>,
3427            snapshot: &MultiBufferSnapshot,
3428        ) -> Vec<(u32, String, bool)> {
3429            snapshot
3430                .excerpt_boundaries_in_range(range)
3431                .map(|boundary| {
3432                    (
3433                        boundary.row,
3434                        boundary
3435                            .buffer
3436                            .text_for_range(boundary.range.context)
3437                            .collect::<String>(),
3438                        boundary.starts_new_buffer,
3439                    )
3440                })
3441                .collect::<Vec<_>>()
3442        }
3443    }
3444
3445    #[gpui::test]
3446    fn test_excerpts_with_context_lines(cx: &mut MutableAppContext) {
3447        let buffer = cx.add_model(|cx| Buffer::new(0, sample_text(20, 3, 'a'), cx));
3448        let multibuffer = cx.add_model(|_| MultiBuffer::new(0));
3449        let anchor_ranges = multibuffer.update(cx, |multibuffer, cx| {
3450            multibuffer.push_excerpts_with_context_lines(
3451                buffer.clone(),
3452                vec![
3453                    Point::new(3, 2)..Point::new(4, 2),
3454                    Point::new(7, 1)..Point::new(7, 3),
3455                    Point::new(15, 0)..Point::new(15, 0),
3456                ],
3457                2,
3458                cx,
3459            )
3460        });
3461
3462        let snapshot = multibuffer.read(cx).snapshot(cx);
3463        assert_eq!(
3464            snapshot.text(),
3465            "bbb\nccc\nddd\neee\nfff\nggg\nhhh\niii\njjj\n\nnnn\nooo\nppp\nqqq\nrrr\n"
3466        );
3467
3468        assert_eq!(
3469            anchor_ranges
3470                .iter()
3471                .map(|range| range.to_point(&snapshot))
3472                .collect::<Vec<_>>(),
3473            vec![
3474                Point::new(2, 2)..Point::new(3, 2),
3475                Point::new(6, 1)..Point::new(6, 3),
3476                Point::new(12, 0)..Point::new(12, 0)
3477            ]
3478        );
3479    }
3480
3481    #[gpui::test]
3482    fn test_empty_excerpt_buffer(cx: &mut MutableAppContext) {
3483        let multibuffer = cx.add_model(|_| MultiBuffer::new(0));
3484
3485        let snapshot = multibuffer.read(cx).snapshot(cx);
3486        assert_eq!(snapshot.text(), "");
3487        assert_eq!(snapshot.buffer_rows(0).collect::<Vec<_>>(), &[Some(0)]);
3488        assert_eq!(snapshot.buffer_rows(1).collect::<Vec<_>>(), &[]);
3489    }
3490
3491    #[gpui::test]
3492    fn test_singleton_multibuffer_anchors(cx: &mut MutableAppContext) {
3493        let buffer = cx.add_model(|cx| Buffer::new(0, "abcd", cx));
3494        let multibuffer = cx.add_model(|cx| MultiBuffer::singleton(buffer.clone(), cx));
3495        let old_snapshot = multibuffer.read(cx).snapshot(cx);
3496        buffer.update(cx, |buffer, cx| {
3497            buffer.edit([(0..0, "X")], cx);
3498            buffer.edit([(5..5, "Y")], cx);
3499        });
3500        let new_snapshot = multibuffer.read(cx).snapshot(cx);
3501
3502        assert_eq!(old_snapshot.text(), "abcd");
3503        assert_eq!(new_snapshot.text(), "XabcdY");
3504
3505        assert_eq!(old_snapshot.anchor_before(0).to_offset(&new_snapshot), 0);
3506        assert_eq!(old_snapshot.anchor_after(0).to_offset(&new_snapshot), 1);
3507        assert_eq!(old_snapshot.anchor_before(4).to_offset(&new_snapshot), 5);
3508        assert_eq!(old_snapshot.anchor_after(4).to_offset(&new_snapshot), 6);
3509    }
3510
3511    #[gpui::test]
3512    fn test_multibuffer_anchors(cx: &mut MutableAppContext) {
3513        let buffer_1 = cx.add_model(|cx| Buffer::new(0, "abcd", cx));
3514        let buffer_2 = cx.add_model(|cx| Buffer::new(0, "efghi", cx));
3515        let multibuffer = cx.add_model(|cx| {
3516            let mut multibuffer = MultiBuffer::new(0);
3517            multibuffer.push_excerpts(
3518                buffer_1.clone(),
3519                [ExcerptRange {
3520                    context: 0..4,
3521                    primary: None,
3522                }],
3523                cx,
3524            );
3525            multibuffer.push_excerpts(
3526                buffer_2.clone(),
3527                [ExcerptRange {
3528                    context: 0..5,
3529                    primary: None,
3530                }],
3531                cx,
3532            );
3533            multibuffer
3534        });
3535        let old_snapshot = multibuffer.read(cx).snapshot(cx);
3536
3537        assert_eq!(old_snapshot.anchor_before(0).to_offset(&old_snapshot), 0);
3538        assert_eq!(old_snapshot.anchor_after(0).to_offset(&old_snapshot), 0);
3539        assert_eq!(Anchor::min().to_offset(&old_snapshot), 0);
3540        assert_eq!(Anchor::min().to_offset(&old_snapshot), 0);
3541        assert_eq!(Anchor::max().to_offset(&old_snapshot), 10);
3542        assert_eq!(Anchor::max().to_offset(&old_snapshot), 10);
3543
3544        buffer_1.update(cx, |buffer, cx| {
3545            buffer.edit([(0..0, "W")], cx);
3546            buffer.edit([(5..5, "X")], cx);
3547        });
3548        buffer_2.update(cx, |buffer, cx| {
3549            buffer.edit([(0..0, "Y")], cx);
3550            buffer.edit([(6..6, "Z")], cx);
3551        });
3552        let new_snapshot = multibuffer.read(cx).snapshot(cx);
3553
3554        assert_eq!(old_snapshot.text(), "abcd\nefghi");
3555        assert_eq!(new_snapshot.text(), "WabcdX\nYefghiZ");
3556
3557        assert_eq!(old_snapshot.anchor_before(0).to_offset(&new_snapshot), 0);
3558        assert_eq!(old_snapshot.anchor_after(0).to_offset(&new_snapshot), 1);
3559        assert_eq!(old_snapshot.anchor_before(1).to_offset(&new_snapshot), 2);
3560        assert_eq!(old_snapshot.anchor_after(1).to_offset(&new_snapshot), 2);
3561        assert_eq!(old_snapshot.anchor_before(2).to_offset(&new_snapshot), 3);
3562        assert_eq!(old_snapshot.anchor_after(2).to_offset(&new_snapshot), 3);
3563        assert_eq!(old_snapshot.anchor_before(5).to_offset(&new_snapshot), 7);
3564        assert_eq!(old_snapshot.anchor_after(5).to_offset(&new_snapshot), 8);
3565        assert_eq!(old_snapshot.anchor_before(10).to_offset(&new_snapshot), 13);
3566        assert_eq!(old_snapshot.anchor_after(10).to_offset(&new_snapshot), 14);
3567    }
3568
3569    #[gpui::test]
3570    fn test_multibuffer_resolving_anchors_after_replacing_their_excerpts(
3571        cx: &mut MutableAppContext,
3572    ) {
3573        let buffer_1 = cx.add_model(|cx| Buffer::new(0, "abcd", cx));
3574        let buffer_2 = cx.add_model(|cx| Buffer::new(0, "ABCDEFGHIJKLMNOP", cx));
3575        let multibuffer = cx.add_model(|_| MultiBuffer::new(0));
3576
3577        // Create an insertion id in buffer 1 that doesn't exist in buffer 2.
3578        // Add an excerpt from buffer 1 that spans this new insertion.
3579        buffer_1.update(cx, |buffer, cx| buffer.edit([(4..4, "123")], cx));
3580        let excerpt_id_1 = multibuffer.update(cx, |multibuffer, cx| {
3581            multibuffer
3582                .push_excerpts(
3583                    buffer_1.clone(),
3584                    [ExcerptRange {
3585                        context: 0..7,
3586                        primary: None,
3587                    }],
3588                    cx,
3589                )
3590                .pop()
3591                .unwrap()
3592        });
3593
3594        let snapshot_1 = multibuffer.read(cx).snapshot(cx);
3595        assert_eq!(snapshot_1.text(), "abcd123");
3596
3597        // Replace the buffer 1 excerpt with new excerpts from buffer 2.
3598        let (excerpt_id_2, excerpt_id_3) = multibuffer.update(cx, |multibuffer, cx| {
3599            multibuffer.remove_excerpts([&excerpt_id_1], cx);
3600            let mut ids = multibuffer
3601                .push_excerpts(
3602                    buffer_2.clone(),
3603                    [
3604                        ExcerptRange {
3605                            context: 0..4,
3606                            primary: None,
3607                        },
3608                        ExcerptRange {
3609                            context: 6..10,
3610                            primary: None,
3611                        },
3612                        ExcerptRange {
3613                            context: 12..16,
3614                            primary: None,
3615                        },
3616                    ],
3617                    cx,
3618                )
3619                .into_iter();
3620            (ids.next().unwrap(), ids.next().unwrap())
3621        });
3622        let snapshot_2 = multibuffer.read(cx).snapshot(cx);
3623        assert_eq!(snapshot_2.text(), "ABCD\nGHIJ\nMNOP");
3624
3625        // The old excerpt id doesn't get reused.
3626        assert_ne!(excerpt_id_2, excerpt_id_1);
3627
3628        // Resolve some anchors from the previous snapshot in the new snapshot.
3629        // Although there is still an excerpt with the same id, it is for
3630        // a different buffer, so we don't attempt to resolve the old text
3631        // anchor in the new buffer.
3632        assert_eq!(
3633            snapshot_2.summary_for_anchor::<usize>(&snapshot_1.anchor_before(2)),
3634            0
3635        );
3636        assert_eq!(
3637            snapshot_2.summaries_for_anchors::<usize, _>(&[
3638                snapshot_1.anchor_before(2),
3639                snapshot_1.anchor_after(3)
3640            ]),
3641            vec![0, 0]
3642        );
3643        let refresh =
3644            snapshot_2.refresh_anchors(&[snapshot_1.anchor_before(2), snapshot_1.anchor_after(3)]);
3645        assert_eq!(
3646            refresh,
3647            &[
3648                (0, snapshot_2.anchor_before(0), false),
3649                (1, snapshot_2.anchor_after(0), false),
3650            ]
3651        );
3652
3653        // Replace the middle excerpt with a smaller excerpt in buffer 2,
3654        // that intersects the old excerpt.
3655        let excerpt_id_5 = multibuffer.update(cx, |multibuffer, cx| {
3656            multibuffer.remove_excerpts([&excerpt_id_3], cx);
3657            multibuffer
3658                .insert_excerpts_after(
3659                    &excerpt_id_3,
3660                    buffer_2.clone(),
3661                    [ExcerptRange {
3662                        context: 5..8,
3663                        primary: None,
3664                    }],
3665                    cx,
3666                )
3667                .pop()
3668                .unwrap()
3669        });
3670
3671        let snapshot_3 = multibuffer.read(cx).snapshot(cx);
3672        assert_eq!(snapshot_3.text(), "ABCD\nFGH\nMNOP");
3673        assert_ne!(excerpt_id_5, excerpt_id_3);
3674
3675        // Resolve some anchors from the previous snapshot in the new snapshot.
3676        // The anchor in the middle excerpt snaps to the beginning of the
3677        // excerpt, since it is not
3678        let anchors = [
3679            snapshot_2.anchor_before(0),
3680            snapshot_2.anchor_after(2),
3681            snapshot_2.anchor_after(6),
3682            snapshot_2.anchor_after(14),
3683        ];
3684        assert_eq!(
3685            snapshot_3.summaries_for_anchors::<usize, _>(&anchors),
3686            &[0, 2, 5, 13]
3687        );
3688
3689        let new_anchors = snapshot_3.refresh_anchors(&anchors);
3690        assert_eq!(
3691            new_anchors.iter().map(|a| (a.0, a.2)).collect::<Vec<_>>(),
3692            &[(0, true), (1, true), (2, true), (3, true)]
3693        );
3694        assert_eq!(
3695            snapshot_3.summaries_for_anchors::<usize, _>(new_anchors.iter().map(|a| &a.1)),
3696            &[0, 2, 7, 13]
3697        );
3698    }
3699
3700    #[gpui::test(iterations = 100)]
3701    fn test_random_multibuffer(cx: &mut MutableAppContext, mut rng: StdRng) {
3702        let operations = env::var("OPERATIONS")
3703            .map(|i| i.parse().expect("invalid `OPERATIONS` variable"))
3704            .unwrap_or(10);
3705
3706        let mut buffers: Vec<ModelHandle<Buffer>> = Vec::new();
3707        let multibuffer = cx.add_model(|_| MultiBuffer::new(0));
3708        let mut excerpt_ids = Vec::new();
3709        let mut expected_excerpts = Vec::<(ModelHandle<Buffer>, Range<text::Anchor>)>::new();
3710        let mut anchors = Vec::new();
3711        let mut old_versions = Vec::new();
3712
3713        for _ in 0..operations {
3714            match rng.gen_range(0..100) {
3715                0..=19 if !buffers.is_empty() => {
3716                    let buffer = buffers.choose(&mut rng).unwrap();
3717                    buffer.update(cx, |buf, cx| buf.randomly_edit(&mut rng, 5, cx));
3718                }
3719                20..=29 if !expected_excerpts.is_empty() => {
3720                    let mut ids_to_remove = vec![];
3721                    for _ in 0..rng.gen_range(1..=3) {
3722                        if expected_excerpts.is_empty() {
3723                            break;
3724                        }
3725
3726                        let ix = rng.gen_range(0..expected_excerpts.len());
3727                        ids_to_remove.push(excerpt_ids.remove(ix));
3728                        let (buffer, range) = expected_excerpts.remove(ix);
3729                        let buffer = buffer.read(cx);
3730                        log::info!(
3731                            "Removing excerpt {}: {:?}",
3732                            ix,
3733                            buffer
3734                                .text_for_range(range.to_offset(&buffer))
3735                                .collect::<String>(),
3736                        );
3737                    }
3738                    ids_to_remove.sort_unstable();
3739                    multibuffer.update(cx, |multibuffer, cx| {
3740                        multibuffer.remove_excerpts(&ids_to_remove, cx)
3741                    });
3742                }
3743                30..=39 if !expected_excerpts.is_empty() => {
3744                    let multibuffer = multibuffer.read(cx).read(cx);
3745                    let offset =
3746                        multibuffer.clip_offset(rng.gen_range(0..=multibuffer.len()), Bias::Left);
3747                    let bias = if rng.gen() { Bias::Left } else { Bias::Right };
3748                    log::info!("Creating anchor at {} with bias {:?}", offset, bias);
3749                    anchors.push(multibuffer.anchor_at(offset, bias));
3750                    anchors.sort_by(|a, b| a.cmp(&b, &multibuffer));
3751                }
3752                40..=44 if !anchors.is_empty() => {
3753                    let multibuffer = multibuffer.read(cx).read(cx);
3754                    let prev_len = anchors.len();
3755                    anchors = multibuffer
3756                        .refresh_anchors(&anchors)
3757                        .into_iter()
3758                        .map(|a| a.1)
3759                        .collect();
3760
3761                    // Ensure the newly-refreshed anchors point to a valid excerpt and don't
3762                    // overshoot its boundaries.
3763                    assert_eq!(anchors.len(), prev_len);
3764                    let mut cursor = multibuffer.excerpts.cursor::<Option<&ExcerptId>>();
3765                    for anchor in &anchors {
3766                        if anchor.excerpt_id == ExcerptId::min()
3767                            || anchor.excerpt_id == ExcerptId::max()
3768                        {
3769                            continue;
3770                        }
3771
3772                        cursor.seek_forward(&Some(&anchor.excerpt_id), Bias::Left, &());
3773                        let excerpt = cursor.item().unwrap();
3774                        assert_eq!(excerpt.id, anchor.excerpt_id);
3775                        assert!(excerpt.contains(anchor));
3776                    }
3777                }
3778                _ => {
3779                    let buffer_handle = if buffers.is_empty() || rng.gen_bool(0.4) {
3780                        let base_text = RandomCharIter::new(&mut rng).take(10).collect::<String>();
3781                        buffers.push(cx.add_model(|cx| Buffer::new(0, base_text, cx)));
3782                        buffers.last().unwrap()
3783                    } else {
3784                        buffers.choose(&mut rng).unwrap()
3785                    };
3786
3787                    let buffer = buffer_handle.read(cx);
3788                    let end_ix = buffer.clip_offset(rng.gen_range(0..=buffer.len()), Bias::Right);
3789                    let start_ix = buffer.clip_offset(rng.gen_range(0..=end_ix), Bias::Left);
3790                    let anchor_range = buffer.anchor_before(start_ix)..buffer.anchor_after(end_ix);
3791                    let prev_excerpt_ix = rng.gen_range(0..=expected_excerpts.len());
3792                    let prev_excerpt_id = excerpt_ids
3793                        .get(prev_excerpt_ix)
3794                        .cloned()
3795                        .unwrap_or(ExcerptId::max());
3796                    let excerpt_ix = (prev_excerpt_ix + 1).min(expected_excerpts.len());
3797
3798                    log::info!(
3799                        "Inserting excerpt at {} of {} for buffer {}: {:?}[{:?}] = {:?}",
3800                        excerpt_ix,
3801                        expected_excerpts.len(),
3802                        buffer_handle.id(),
3803                        buffer.text(),
3804                        start_ix..end_ix,
3805                        &buffer.text()[start_ix..end_ix]
3806                    );
3807
3808                    let excerpt_id = multibuffer.update(cx, |multibuffer, cx| {
3809                        multibuffer
3810                            .insert_excerpts_after(
3811                                &prev_excerpt_id,
3812                                buffer_handle.clone(),
3813                                [ExcerptRange {
3814                                    context: start_ix..end_ix,
3815                                    primary: None,
3816                                }],
3817                                cx,
3818                            )
3819                            .pop()
3820                            .unwrap()
3821                    });
3822
3823                    excerpt_ids.insert(excerpt_ix, excerpt_id);
3824                    expected_excerpts.insert(excerpt_ix, (buffer_handle.clone(), anchor_range));
3825                }
3826            }
3827
3828            if rng.gen_bool(0.3) {
3829                multibuffer.update(cx, |multibuffer, cx| {
3830                    old_versions.push((multibuffer.snapshot(cx), multibuffer.subscribe()));
3831                })
3832            }
3833
3834            let snapshot = multibuffer.read(cx).snapshot(cx);
3835
3836            let mut excerpt_starts = Vec::new();
3837            let mut expected_text = String::new();
3838            let mut expected_buffer_rows = Vec::new();
3839            for (buffer, range) in &expected_excerpts {
3840                let buffer = buffer.read(cx);
3841                let buffer_range = range.to_offset(buffer);
3842
3843                excerpt_starts.push(TextSummary::from(expected_text.as_str()));
3844                expected_text.extend(buffer.text_for_range(buffer_range.clone()));
3845                expected_text.push('\n');
3846
3847                let buffer_row_range = buffer.offset_to_point(buffer_range.start).row
3848                    ..=buffer.offset_to_point(buffer_range.end).row;
3849                for row in buffer_row_range {
3850                    expected_buffer_rows.push(Some(row));
3851                }
3852            }
3853            // Remove final trailing newline.
3854            if !expected_excerpts.is_empty() {
3855                expected_text.pop();
3856            }
3857
3858            // Always report one buffer row
3859            if expected_buffer_rows.is_empty() {
3860                expected_buffer_rows.push(Some(0));
3861            }
3862
3863            assert_eq!(snapshot.text(), expected_text);
3864            log::info!("MultiBuffer text: {:?}", expected_text);
3865
3866            assert_eq!(
3867                snapshot.buffer_rows(0).collect::<Vec<_>>(),
3868                expected_buffer_rows,
3869            );
3870
3871            for _ in 0..5 {
3872                let start_row = rng.gen_range(0..=expected_buffer_rows.len());
3873                assert_eq!(
3874                    snapshot.buffer_rows(start_row as u32).collect::<Vec<_>>(),
3875                    &expected_buffer_rows[start_row..],
3876                    "buffer_rows({})",
3877                    start_row
3878                );
3879            }
3880
3881            assert_eq!(
3882                snapshot.max_buffer_row(),
3883                expected_buffer_rows
3884                    .into_iter()
3885                    .filter_map(|r| r)
3886                    .max()
3887                    .unwrap()
3888            );
3889
3890            let mut excerpt_starts = excerpt_starts.into_iter();
3891            for (buffer, range) in &expected_excerpts {
3892                let buffer_id = buffer.id();
3893                let buffer = buffer.read(cx);
3894                let buffer_range = range.to_offset(buffer);
3895                let buffer_start_point = buffer.offset_to_point(buffer_range.start);
3896                let buffer_start_point_utf16 =
3897                    buffer.text_summary_for_range::<PointUtf16, _>(0..buffer_range.start);
3898
3899                let excerpt_start = excerpt_starts.next().unwrap();
3900                let mut offset = excerpt_start.len;
3901                let mut buffer_offset = buffer_range.start;
3902                let mut point = excerpt_start.lines;
3903                let mut buffer_point = buffer_start_point;
3904                let mut point_utf16 = excerpt_start.lines_utf16;
3905                let mut buffer_point_utf16 = buffer_start_point_utf16;
3906                for ch in buffer
3907                    .snapshot()
3908                    .chunks(buffer_range.clone(), false)
3909                    .flat_map(|c| c.text.chars())
3910                {
3911                    for _ in 0..ch.len_utf8() {
3912                        let left_offset = snapshot.clip_offset(offset, Bias::Left);
3913                        let right_offset = snapshot.clip_offset(offset, Bias::Right);
3914                        let buffer_left_offset = buffer.clip_offset(buffer_offset, Bias::Left);
3915                        let buffer_right_offset = buffer.clip_offset(buffer_offset, Bias::Right);
3916                        assert_eq!(
3917                            left_offset,
3918                            excerpt_start.len + (buffer_left_offset - buffer_range.start),
3919                            "clip_offset({:?}, Left). buffer: {:?}, buffer offset: {:?}",
3920                            offset,
3921                            buffer_id,
3922                            buffer_offset,
3923                        );
3924                        assert_eq!(
3925                            right_offset,
3926                            excerpt_start.len + (buffer_right_offset - buffer_range.start),
3927                            "clip_offset({:?}, Right). buffer: {:?}, buffer offset: {:?}",
3928                            offset,
3929                            buffer_id,
3930                            buffer_offset,
3931                        );
3932
3933                        let left_point = snapshot.clip_point(point, Bias::Left);
3934                        let right_point = snapshot.clip_point(point, Bias::Right);
3935                        let buffer_left_point = buffer.clip_point(buffer_point, Bias::Left);
3936                        let buffer_right_point = buffer.clip_point(buffer_point, Bias::Right);
3937                        assert_eq!(
3938                            left_point,
3939                            excerpt_start.lines + (buffer_left_point - buffer_start_point),
3940                            "clip_point({:?}, Left). buffer: {:?}, buffer point: {:?}",
3941                            point,
3942                            buffer_id,
3943                            buffer_point,
3944                        );
3945                        assert_eq!(
3946                            right_point,
3947                            excerpt_start.lines + (buffer_right_point - buffer_start_point),
3948                            "clip_point({:?}, Right). buffer: {:?}, buffer point: {:?}",
3949                            point,
3950                            buffer_id,
3951                            buffer_point,
3952                        );
3953
3954                        assert_eq!(
3955                            snapshot.point_to_offset(left_point),
3956                            left_offset,
3957                            "point_to_offset({:?})",
3958                            left_point,
3959                        );
3960                        assert_eq!(
3961                            snapshot.offset_to_point(left_offset),
3962                            left_point,
3963                            "offset_to_point({:?})",
3964                            left_offset,
3965                        );
3966
3967                        offset += 1;
3968                        buffer_offset += 1;
3969                        if ch == '\n' {
3970                            point += Point::new(1, 0);
3971                            buffer_point += Point::new(1, 0);
3972                        } else {
3973                            point += Point::new(0, 1);
3974                            buffer_point += Point::new(0, 1);
3975                        }
3976                    }
3977
3978                    for _ in 0..ch.len_utf16() {
3979                        let left_point_utf16 = snapshot.clip_point_utf16(point_utf16, Bias::Left);
3980                        let right_point_utf16 = snapshot.clip_point_utf16(point_utf16, Bias::Right);
3981                        let buffer_left_point_utf16 =
3982                            buffer.clip_point_utf16(buffer_point_utf16, Bias::Left);
3983                        let buffer_right_point_utf16 =
3984                            buffer.clip_point_utf16(buffer_point_utf16, Bias::Right);
3985                        assert_eq!(
3986                            left_point_utf16,
3987                            excerpt_start.lines_utf16
3988                                + (buffer_left_point_utf16 - buffer_start_point_utf16),
3989                            "clip_point_utf16({:?}, Left). buffer: {:?}, buffer point_utf16: {:?}",
3990                            point_utf16,
3991                            buffer_id,
3992                            buffer_point_utf16,
3993                        );
3994                        assert_eq!(
3995                            right_point_utf16,
3996                            excerpt_start.lines_utf16
3997                                + (buffer_right_point_utf16 - buffer_start_point_utf16),
3998                            "clip_point_utf16({:?}, Right). buffer: {:?}, buffer point_utf16: {:?}",
3999                            point_utf16,
4000                            buffer_id,
4001                            buffer_point_utf16,
4002                        );
4003
4004                        if ch == '\n' {
4005                            point_utf16 += PointUtf16::new(1, 0);
4006                            buffer_point_utf16 += PointUtf16::new(1, 0);
4007                        } else {
4008                            point_utf16 += PointUtf16::new(0, 1);
4009                            buffer_point_utf16 += PointUtf16::new(0, 1);
4010                        }
4011                    }
4012                }
4013            }
4014
4015            for (row, line) in expected_text.split('\n').enumerate() {
4016                assert_eq!(
4017                    snapshot.line_len(row as u32),
4018                    line.len() as u32,
4019                    "line_len({}).",
4020                    row
4021                );
4022            }
4023
4024            let text_rope = Rope::from(expected_text.as_str());
4025            for _ in 0..10 {
4026                let end_ix = text_rope.clip_offset(rng.gen_range(0..=text_rope.len()), Bias::Right);
4027                let start_ix = text_rope.clip_offset(rng.gen_range(0..=end_ix), Bias::Left);
4028
4029                let text_for_range = snapshot
4030                    .text_for_range(start_ix..end_ix)
4031                    .collect::<String>();
4032                assert_eq!(
4033                    text_for_range,
4034                    &expected_text[start_ix..end_ix],
4035                    "incorrect text for range {:?}",
4036                    start_ix..end_ix
4037                );
4038
4039                let excerpted_buffer_ranges = multibuffer
4040                    .read(cx)
4041                    .range_to_buffer_ranges(start_ix..end_ix, cx);
4042                let excerpted_buffers_text = excerpted_buffer_ranges
4043                    .into_iter()
4044                    .map(|(buffer, buffer_range)| {
4045                        buffer
4046                            .read(cx)
4047                            .text_for_range(buffer_range)
4048                            .collect::<String>()
4049                    })
4050                    .collect::<Vec<_>>()
4051                    .join("\n");
4052                assert_eq!(excerpted_buffers_text, text_for_range);
4053
4054                let expected_summary = TextSummary::from(&expected_text[start_ix..end_ix]);
4055                assert_eq!(
4056                    snapshot.text_summary_for_range::<TextSummary, _>(start_ix..end_ix),
4057                    expected_summary,
4058                    "incorrect summary for range {:?}",
4059                    start_ix..end_ix
4060                );
4061            }
4062
4063            // Anchor resolution
4064            let summaries = snapshot.summaries_for_anchors::<usize, _>(&anchors);
4065            assert_eq!(anchors.len(), summaries.len());
4066            for (anchor, resolved_offset) in anchors.iter().zip(summaries) {
4067                assert!(resolved_offset <= snapshot.len());
4068                assert_eq!(
4069                    snapshot.summary_for_anchor::<usize>(anchor),
4070                    resolved_offset
4071                );
4072            }
4073
4074            for _ in 0..10 {
4075                let end_ix = text_rope.clip_offset(rng.gen_range(0..=text_rope.len()), Bias::Right);
4076                assert_eq!(
4077                    snapshot.reversed_chars_at(end_ix).collect::<String>(),
4078                    expected_text[..end_ix].chars().rev().collect::<String>(),
4079                );
4080            }
4081
4082            for _ in 0..10 {
4083                let end_ix = rng.gen_range(0..=text_rope.len());
4084                let start_ix = rng.gen_range(0..=end_ix);
4085                assert_eq!(
4086                    snapshot
4087                        .bytes_in_range(start_ix..end_ix)
4088                        .flatten()
4089                        .copied()
4090                        .collect::<Vec<_>>(),
4091                    expected_text.as_bytes()[start_ix..end_ix].to_vec(),
4092                    "bytes_in_range({:?})",
4093                    start_ix..end_ix,
4094                );
4095            }
4096        }
4097
4098        let snapshot = multibuffer.read(cx).snapshot(cx);
4099        for (old_snapshot, subscription) in old_versions {
4100            let edits = subscription.consume().into_inner();
4101
4102            log::info!(
4103                "applying subscription edits to old text: {:?}: {:?}",
4104                old_snapshot.text(),
4105                edits,
4106            );
4107
4108            let mut text = old_snapshot.text();
4109            for edit in edits {
4110                let new_text: String = snapshot.text_for_range(edit.new.clone()).collect();
4111                text.replace_range(edit.new.start..edit.new.start + edit.old.len(), &new_text);
4112            }
4113            assert_eq!(text.to_string(), snapshot.text());
4114        }
4115    }
4116
4117    #[gpui::test]
4118    fn test_history(cx: &mut MutableAppContext) {
4119        cx.set_global(Settings::test(cx));
4120        let buffer_1 = cx.add_model(|cx| Buffer::new(0, "1234", cx));
4121        let buffer_2 = cx.add_model(|cx| Buffer::new(0, "5678", cx));
4122        let multibuffer = cx.add_model(|_| MultiBuffer::new(0));
4123        let group_interval = multibuffer.read(cx).history.group_interval;
4124        multibuffer.update(cx, |multibuffer, cx| {
4125            multibuffer.push_excerpts(
4126                buffer_1.clone(),
4127                [ExcerptRange {
4128                    context: 0..buffer_1.read(cx).len(),
4129                    primary: None,
4130                }],
4131                cx,
4132            );
4133            multibuffer.push_excerpts(
4134                buffer_2.clone(),
4135                [ExcerptRange {
4136                    context: 0..buffer_2.read(cx).len(),
4137                    primary: None,
4138                }],
4139                cx,
4140            );
4141        });
4142
4143        let mut now = Instant::now();
4144
4145        multibuffer.update(cx, |multibuffer, cx| {
4146            multibuffer.start_transaction_at(now, cx);
4147            multibuffer.edit(
4148                [
4149                    (Point::new(0, 0)..Point::new(0, 0), "A"),
4150                    (Point::new(1, 0)..Point::new(1, 0), "A"),
4151                ],
4152                cx,
4153            );
4154            multibuffer.edit(
4155                [
4156                    (Point::new(0, 1)..Point::new(0, 1), "B"),
4157                    (Point::new(1, 1)..Point::new(1, 1), "B"),
4158                ],
4159                cx,
4160            );
4161            multibuffer.end_transaction_at(now, cx);
4162            assert_eq!(multibuffer.read(cx).text(), "AB1234\nAB5678");
4163
4164            // Edit buffer 1 through the multibuffer
4165            now += 2 * group_interval;
4166            multibuffer.start_transaction_at(now, cx);
4167            multibuffer.edit([(2..2, "C")], cx);
4168            multibuffer.end_transaction_at(now, cx);
4169            assert_eq!(multibuffer.read(cx).text(), "ABC1234\nAB5678");
4170
4171            // Edit buffer 1 independently
4172            buffer_1.update(cx, |buffer_1, cx| {
4173                buffer_1.start_transaction_at(now);
4174                buffer_1.edit([(3..3, "D")], cx);
4175                buffer_1.end_transaction_at(now, cx);
4176
4177                now += 2 * group_interval;
4178                buffer_1.start_transaction_at(now);
4179                buffer_1.edit([(4..4, "E")], cx);
4180                buffer_1.end_transaction_at(now, cx);
4181            });
4182            assert_eq!(multibuffer.read(cx).text(), "ABCDE1234\nAB5678");
4183
4184            // An undo in the multibuffer undoes the multibuffer transaction
4185            // and also any individual buffer edits that have occured since
4186            // that transaction.
4187            multibuffer.undo(cx);
4188            assert_eq!(multibuffer.read(cx).text(), "AB1234\nAB5678");
4189
4190            multibuffer.undo(cx);
4191            assert_eq!(multibuffer.read(cx).text(), "1234\n5678");
4192
4193            multibuffer.redo(cx);
4194            assert_eq!(multibuffer.read(cx).text(), "AB1234\nAB5678");
4195
4196            multibuffer.redo(cx);
4197            assert_eq!(multibuffer.read(cx).text(), "ABCDE1234\nAB5678");
4198
4199            // Undo buffer 2 independently.
4200            buffer_2.update(cx, |buffer_2, cx| buffer_2.undo(cx));
4201            assert_eq!(multibuffer.read(cx).text(), "ABCDE1234\n5678");
4202
4203            // An undo in the multibuffer undoes the components of the
4204            // the last multibuffer transaction that are not already undone.
4205            multibuffer.undo(cx);
4206            assert_eq!(multibuffer.read(cx).text(), "AB1234\n5678");
4207
4208            multibuffer.undo(cx);
4209            assert_eq!(multibuffer.read(cx).text(), "1234\n5678");
4210
4211            multibuffer.redo(cx);
4212            assert_eq!(multibuffer.read(cx).text(), "AB1234\nAB5678");
4213
4214            buffer_1.update(cx, |buffer_1, cx| buffer_1.redo(cx));
4215            assert_eq!(multibuffer.read(cx).text(), "ABCD1234\nAB5678");
4216
4217            // Redo stack gets cleared after an edit.
4218            now += 2 * group_interval;
4219            multibuffer.start_transaction_at(now, cx);
4220            multibuffer.edit([(0..0, "X")], cx);
4221            multibuffer.end_transaction_at(now, cx);
4222            assert_eq!(multibuffer.read(cx).text(), "XABCD1234\nAB5678");
4223            multibuffer.redo(cx);
4224            assert_eq!(multibuffer.read(cx).text(), "XABCD1234\nAB5678");
4225            multibuffer.undo(cx);
4226            assert_eq!(multibuffer.read(cx).text(), "ABCD1234\nAB5678");
4227            multibuffer.undo(cx);
4228            assert_eq!(multibuffer.read(cx).text(), "1234\n5678");
4229        });
4230    }
4231}