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