multi_buffer.rs

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