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