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