multi_buffer.rs

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