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