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