multi_buffer.rs

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