multi_buffer.rs

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