1mod anchor;
2
3pub use anchor::{Anchor, AnchorRangeExt};
4use anyhow::Result;
5use clock::ReplicaId;
6use collections::{Bound, HashMap};
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
61struct Transaction {
62 id: TransactionId,
63 buffer_transactions: HashMap<usize, text::TransactionId>,
64 first_edit_at: Instant,
65 last_edit_at: Instant,
66 suppress_grouping: bool,
67}
68
69pub trait ToOffset: 'static + fmt::Debug {
70 fn to_offset(&self, snapshot: &MultiBufferSnapshot) -> usize;
71}
72
73pub trait ToPoint: 'static + fmt::Debug {
74 fn to_point(&self, snapshot: &MultiBufferSnapshot) -> Point;
75}
76
77pub trait ToPointUtf16: 'static + fmt::Debug {
78 fn to_point_utf16(&self, snapshot: &MultiBufferSnapshot) -> PointUtf16;
79}
80
81struct BufferState {
82 buffer: ModelHandle<Buffer>,
83 last_version: clock::Global,
84 last_parse_count: usize,
85 last_selections_update_count: usize,
86 last_diagnostics_update_count: usize,
87 last_file_update_count: usize,
88 excerpts: Vec<ExcerptId>,
89 _subscriptions: [gpui::Subscription; 2],
90}
91
92#[derive(Clone, Default)]
93pub struct MultiBufferSnapshot {
94 singleton: bool,
95 excerpts: SumTree<Excerpt>,
96 parse_count: usize,
97 diagnostics_update_count: usize,
98 trailing_excerpt_update_count: usize,
99 is_dirty: bool,
100 has_conflict: bool,
101}
102
103pub struct ExcerptBoundary {
104 pub row: u32,
105 pub buffer: BufferSnapshot,
106 pub range: Range<text::Anchor>,
107 pub starts_new_buffer: bool,
108}
109
110#[derive(Clone)]
111struct Excerpt {
112 id: ExcerptId,
113 buffer_id: usize,
114 buffer: BufferSnapshot,
115 range: Range<text::Anchor>,
116 max_buffer_row: u32,
117 text_summary: TextSummary,
118 has_trailing_newline: bool,
119}
120
121#[derive(Clone, Debug, Default)]
122struct ExcerptSummary {
123 excerpt_id: ExcerptId,
124 max_buffer_row: u32,
125 text: TextSummary,
126}
127
128pub struct MultiBufferRows<'a> {
129 buffer_row_range: Range<u32>,
130 excerpts: Cursor<'a, Excerpt, Point>,
131}
132
133pub struct MultiBufferChunks<'a> {
134 range: Range<usize>,
135 excerpts: Cursor<'a, Excerpt, usize>,
136 excerpt_chunks: Option<ExcerptChunks<'a>>,
137 language_aware: bool,
138}
139
140pub struct MultiBufferBytes<'a> {
141 range: Range<usize>,
142 excerpts: Cursor<'a, Excerpt, usize>,
143 excerpt_bytes: Option<ExcerptBytes<'a>>,
144 chunk: &'a [u8],
145}
146
147struct ExcerptChunks<'a> {
148 content_chunks: BufferChunks<'a>,
149 footer_height: usize,
150}
151
152struct ExcerptBytes<'a> {
153 content_bytes: language::rope::Bytes<'a>,
154 footer_height: usize,
155}
156
157impl MultiBuffer {
158 pub fn new(replica_id: ReplicaId) -> Self {
159 Self {
160 snapshot: Default::default(),
161 buffers: Default::default(),
162 subscriptions: Default::default(),
163 singleton: false,
164 replica_id,
165 history: History {
166 next_transaction_id: Default::default(),
167 undo_stack: Default::default(),
168 redo_stack: Default::default(),
169 transaction_depth: 0,
170 group_interval: Duration::from_millis(300),
171 },
172 title: Default::default(),
173 }
174 }
175
176 pub fn with_title(mut self, title: String) -> Self {
177 self.title = Some(title);
178 self
179 }
180
181 pub fn singleton(buffer: ModelHandle<Buffer>, cx: &mut ModelContext<Self>) -> Self {
182 let mut this = Self::new(buffer.read(cx).replica_id());
183 this.singleton = true;
184 this.push_excerpts(buffer, [text::Anchor::min()..text::Anchor::max()], cx);
185 this.snapshot.borrow_mut().singleton = true;
186 this
187 }
188
189 #[cfg(any(test, feature = "test-support"))]
190 pub fn build_simple(text: &str, cx: &mut gpui::MutableAppContext) -> ModelHandle<Self> {
191 let buffer = cx.add_model(|cx| Buffer::new(0, text, cx));
192 cx.add_model(|cx| Self::singleton(buffer, cx))
193 }
194
195 #[cfg(any(test, feature = "test-support"))]
196 pub fn build_random(
197 rng: &mut impl rand::Rng,
198 cx: &mut gpui::MutableAppContext,
199 ) -> ModelHandle<Self> {
200 cx.add_model(|cx| {
201 let mut multibuffer = MultiBuffer::new(0);
202 let mutation_count = rng.gen_range(1..=5);
203 multibuffer.randomly_edit_excerpts(rng, mutation_count, cx);
204 multibuffer
205 })
206 }
207
208 pub fn replica_id(&self) -> ReplicaId {
209 self.replica_id
210 }
211
212 pub fn snapshot(&self, cx: &AppContext) -> MultiBufferSnapshot {
213 self.sync(cx);
214 self.snapshot.borrow().clone()
215 }
216
217 pub fn read(&self, cx: &AppContext) -> Ref<MultiBufferSnapshot> {
218 self.sync(cx);
219 self.snapshot.borrow()
220 }
221
222 pub fn as_singleton(&self) -> Option<ModelHandle<Buffer>> {
223 if self.singleton {
224 return Some(
225 self.buffers
226 .borrow()
227 .values()
228 .next()
229 .unwrap()
230 .buffer
231 .clone(),
232 );
233 } else {
234 None
235 }
236 }
237
238 pub fn is_singleton(&self) -> bool {
239 self.singleton
240 }
241
242 pub fn subscribe(&mut self) -> Subscription {
243 self.subscriptions.subscribe()
244 }
245
246 pub fn edit<I, S, T>(&mut self, ranges: I, new_text: T, cx: &mut ModelContext<Self>)
247 where
248 I: IntoIterator<Item = Range<S>>,
249 S: ToOffset,
250 T: Into<String>,
251 {
252 self.edit_internal(ranges, new_text, false, cx)
253 }
254
255 pub fn edit_with_autoindent<I, S, T>(
256 &mut self,
257 ranges: I,
258 new_text: T,
259 cx: &mut ModelContext<Self>,
260 ) where
261 I: IntoIterator<Item = Range<S>>,
262 S: ToOffset,
263 T: Into<String>,
264 {
265 self.edit_internal(ranges, new_text, true, cx)
266 }
267
268 pub fn edit_internal<I, S, T>(
269 &mut self,
270 ranges_iter: I,
271 new_text: T,
272 autoindent: bool,
273 cx: &mut ModelContext<Self>,
274 ) where
275 I: IntoIterator<Item = Range<S>>,
276 S: ToOffset,
277 T: Into<String>,
278 {
279 if self.buffers.borrow().is_empty() {
280 return;
281 }
282
283 if let Some(buffer) = self.as_singleton() {
284 let snapshot = self.read(cx);
285 let ranges = ranges_iter
286 .into_iter()
287 .map(|range| range.start.to_offset(&snapshot)..range.end.to_offset(&snapshot));
288 return buffer.update(cx, |buffer, cx| {
289 if autoindent {
290 buffer.edit_with_autoindent(ranges, new_text, cx);
291 } else {
292 buffer.edit(ranges, new_text, cx);
293 }
294 });
295 }
296
297 let snapshot = self.read(cx);
298 let mut buffer_edits: HashMap<usize, Vec<(Range<usize>, bool)>> = Default::default();
299 let mut cursor = snapshot.excerpts.cursor::<usize>();
300 for range in ranges_iter {
301 let start = range.start.to_offset(&snapshot);
302 let end = range.end.to_offset(&snapshot);
303 cursor.seek(&start, Bias::Right, &());
304 if cursor.item().is_none() && start == *cursor.start() {
305 cursor.prev(&());
306 }
307 let start_excerpt = cursor.item().expect("start offset out of bounds");
308 let start_overshoot = start - cursor.start();
309 let buffer_start =
310 start_excerpt.range.start.to_offset(&start_excerpt.buffer) + start_overshoot;
311
312 cursor.seek(&end, Bias::Right, &());
313 if cursor.item().is_none() && end == *cursor.start() {
314 cursor.prev(&());
315 }
316 let end_excerpt = cursor.item().expect("end offset out of bounds");
317 let end_overshoot = end - cursor.start();
318 let buffer_end = end_excerpt.range.start.to_offset(&end_excerpt.buffer) + end_overshoot;
319
320 if start_excerpt.id == end_excerpt.id {
321 buffer_edits
322 .entry(start_excerpt.buffer_id)
323 .or_insert(Vec::new())
324 .push((buffer_start..buffer_end, true));
325 } else {
326 let start_excerpt_range =
327 buffer_start..start_excerpt.range.end.to_offset(&start_excerpt.buffer);
328 let end_excerpt_range =
329 end_excerpt.range.start.to_offset(&end_excerpt.buffer)..buffer_end;
330 buffer_edits
331 .entry(start_excerpt.buffer_id)
332 .or_insert(Vec::new())
333 .push((start_excerpt_range, true));
334 buffer_edits
335 .entry(end_excerpt.buffer_id)
336 .or_insert(Vec::new())
337 .push((end_excerpt_range, false));
338
339 cursor.seek(&start, Bias::Right, &());
340 cursor.next(&());
341 while let Some(excerpt) = cursor.item() {
342 if excerpt.id == end_excerpt.id {
343 break;
344 }
345 buffer_edits
346 .entry(excerpt.buffer_id)
347 .or_insert(Vec::new())
348 .push((excerpt.range.to_offset(&excerpt.buffer), false));
349 cursor.next(&());
350 }
351 }
352 }
353
354 let new_text = new_text.into();
355 for (buffer_id, mut edits) in buffer_edits {
356 edits.sort_unstable_by_key(|(range, _)| range.start);
357 self.buffers.borrow()[&buffer_id]
358 .buffer
359 .update(cx, |buffer, cx| {
360 let mut edits = edits.into_iter().peekable();
361 let mut insertions = Vec::new();
362 let mut deletions = Vec::new();
363 while let Some((mut range, mut is_insertion)) = edits.next() {
364 while let Some((next_range, next_is_insertion)) = edits.peek() {
365 if range.end >= next_range.start {
366 range.end = cmp::max(next_range.end, range.end);
367 is_insertion |= *next_is_insertion;
368 edits.next();
369 } else {
370 break;
371 }
372 }
373
374 if is_insertion {
375 insertions.push(
376 buffer.anchor_before(range.start)..buffer.anchor_before(range.end),
377 );
378 } else if !range.is_empty() {
379 deletions.push(
380 buffer.anchor_before(range.start)..buffer.anchor_before(range.end),
381 );
382 }
383 }
384
385 if autoindent {
386 buffer.edit_with_autoindent(deletions, "", cx);
387 buffer.edit_with_autoindent(insertions, new_text.clone(), cx);
388 } else {
389 buffer.edit(deletions, "", cx);
390 buffer.edit(insertions, new_text.clone(), cx);
391 }
392 })
393 }
394 }
395
396 pub fn start_transaction(&mut self, cx: &mut ModelContext<Self>) -> Option<TransactionId> {
397 self.start_transaction_at(Instant::now(), cx)
398 }
399
400 pub(crate) fn start_transaction_at(
401 &mut self,
402 now: Instant,
403 cx: &mut ModelContext<Self>,
404 ) -> Option<TransactionId> {
405 if let Some(buffer) = self.as_singleton() {
406 return buffer.update(cx, |buffer, _| buffer.start_transaction_at(now));
407 }
408
409 for BufferState { buffer, .. } in self.buffers.borrow().values() {
410 buffer.update(cx, |buffer, _| buffer.start_transaction_at(now));
411 }
412 self.history.start_transaction(now)
413 }
414
415 pub fn end_transaction(&mut self, cx: &mut ModelContext<Self>) -> Option<TransactionId> {
416 self.end_transaction_at(Instant::now(), cx)
417 }
418
419 pub(crate) fn end_transaction_at(
420 &mut self,
421 now: Instant,
422 cx: &mut ModelContext<Self>,
423 ) -> Option<TransactionId> {
424 if let Some(buffer) = self.as_singleton() {
425 return buffer.update(cx, |buffer, cx| buffer.end_transaction_at(now, cx));
426 }
427
428 let mut buffer_transactions = HashMap::default();
429 for BufferState { buffer, .. } in self.buffers.borrow().values() {
430 if let Some(transaction_id) =
431 buffer.update(cx, |buffer, cx| buffer.end_transaction_at(now, cx))
432 {
433 buffer_transactions.insert(buffer.id(), transaction_id);
434 }
435 }
436
437 if self.history.end_transaction(now, buffer_transactions) {
438 let transaction_id = self.history.group().unwrap();
439 Some(transaction_id)
440 } else {
441 None
442 }
443 }
444
445 pub fn finalize_last_transaction(&mut self, cx: &mut ModelContext<Self>) {
446 self.history.finalize_last_transaction();
447 for BufferState { buffer, .. } in self.buffers.borrow().values() {
448 buffer.update(cx, |buffer, _| {
449 buffer.finalize_last_transaction();
450 });
451 }
452 }
453
454 pub fn push_transaction<'a, T>(&mut self, buffer_transactions: T)
455 where
456 T: IntoIterator<Item = (&'a ModelHandle<Buffer>, &'a language::Transaction)>,
457 {
458 self.history
459 .push_transaction(buffer_transactions, Instant::now());
460 self.history.finalize_last_transaction();
461 }
462
463 pub fn set_active_selections(
464 &mut self,
465 selections: &[Selection<Anchor>],
466 cx: &mut ModelContext<Self>,
467 ) {
468 let mut selections_by_buffer: HashMap<usize, Vec<Selection<text::Anchor>>> =
469 Default::default();
470 let snapshot = self.read(cx);
471 let mut cursor = snapshot.excerpts.cursor::<Option<&ExcerptId>>();
472 for selection in selections {
473 cursor.seek(&Some(&selection.start.excerpt_id), Bias::Left, &());
474 while let Some(excerpt) = cursor.item() {
475 if excerpt.id > selection.end.excerpt_id {
476 break;
477 }
478
479 let mut start = excerpt.range.start.clone();
480 let mut end = excerpt.range.end.clone();
481 if excerpt.id == selection.start.excerpt_id {
482 start = selection.start.text_anchor.clone();
483 }
484 if excerpt.id == selection.end.excerpt_id {
485 end = selection.end.text_anchor.clone();
486 }
487 selections_by_buffer
488 .entry(excerpt.buffer_id)
489 .or_default()
490 .push(Selection {
491 id: selection.id,
492 start,
493 end,
494 reversed: selection.reversed,
495 goal: selection.goal,
496 });
497
498 cursor.next(&());
499 }
500 }
501
502 for (buffer_id, buffer_state) in self.buffers.borrow().iter() {
503 if !selections_by_buffer.contains_key(buffer_id) {
504 buffer_state
505 .buffer
506 .update(cx, |buffer, cx| buffer.remove_active_selections(cx));
507 }
508 }
509
510 for (buffer_id, mut selections) in selections_by_buffer {
511 self.buffers.borrow()[&buffer_id]
512 .buffer
513 .update(cx, |buffer, cx| {
514 selections.sort_unstable_by(|a, b| a.start.cmp(&b.start, buffer).unwrap());
515 let mut selections = selections.into_iter().peekable();
516 let merged_selections = Arc::from_iter(iter::from_fn(|| {
517 let mut selection = selections.next()?;
518 while let Some(next_selection) = selections.peek() {
519 if selection
520 .end
521 .cmp(&next_selection.start, buffer)
522 .unwrap()
523 .is_ge()
524 {
525 let next_selection = selections.next().unwrap();
526 if next_selection
527 .end
528 .cmp(&selection.end, buffer)
529 .unwrap()
530 .is_ge()
531 {
532 selection.end = next_selection.end;
533 }
534 } else {
535 break;
536 }
537 }
538 Some(selection)
539 }));
540 buffer.set_active_selections(merged_selections, cx);
541 });
542 }
543 }
544
545 pub fn remove_active_selections(&mut self, cx: &mut ModelContext<Self>) {
546 for buffer in self.buffers.borrow().values() {
547 buffer
548 .buffer
549 .update(cx, |buffer, cx| buffer.remove_active_selections(cx));
550 }
551 }
552
553 pub fn undo(&mut self, cx: &mut ModelContext<Self>) -> Option<TransactionId> {
554 if let Some(buffer) = self.as_singleton() {
555 return buffer.update(cx, |buffer, cx| buffer.undo(cx));
556 }
557
558 while let Some(transaction) = self.history.pop_undo() {
559 let mut undone = false;
560 for (buffer_id, buffer_transaction_id) in &mut transaction.buffer_transactions {
561 if let Some(BufferState { buffer, .. }) = self.buffers.borrow().get(&buffer_id) {
562 undone |= buffer.update(cx, |buffer, cx| {
563 let undo_to = *buffer_transaction_id;
564 if let Some(entry) = buffer.peek_undo_stack() {
565 *buffer_transaction_id = entry.transaction_id();
566 }
567 buffer.undo_to_transaction(undo_to, cx)
568 });
569 }
570 }
571
572 if undone {
573 return Some(transaction.id);
574 }
575 }
576
577 None
578 }
579
580 pub fn redo(&mut self, cx: &mut ModelContext<Self>) -> Option<TransactionId> {
581 if let Some(buffer) = self.as_singleton() {
582 return buffer.update(cx, |buffer, cx| buffer.redo(cx));
583 }
584
585 while let Some(transaction) = self.history.pop_redo() {
586 let mut redone = false;
587 for (buffer_id, buffer_transaction_id) in &mut transaction.buffer_transactions {
588 if let Some(BufferState { buffer, .. }) = self.buffers.borrow().get(&buffer_id) {
589 redone |= buffer.update(cx, |buffer, cx| {
590 let redo_to = *buffer_transaction_id;
591 if let Some(entry) = buffer.peek_redo_stack() {
592 *buffer_transaction_id = entry.transaction_id();
593 }
594 buffer.redo_to_transaction(redo_to, cx)
595 });
596 }
597 }
598
599 if redone {
600 return Some(transaction.id);
601 }
602 }
603
604 None
605 }
606
607 pub fn push_excerpts<O>(
608 &mut self,
609 buffer: ModelHandle<Buffer>,
610 ranges: impl IntoIterator<Item = Range<O>>,
611 cx: &mut ModelContext<Self>,
612 ) -> Vec<ExcerptId>
613 where
614 O: text::ToOffset,
615 {
616 self.insert_excerpts_after(&ExcerptId::max(), buffer, ranges, cx)
617 }
618
619 pub fn push_excerpts_with_context_lines<O>(
620 &mut self,
621 buffer: ModelHandle<Buffer>,
622 ranges: Vec<Range<O>>,
623 context_line_count: u32,
624 cx: &mut ModelContext<Self>,
625 ) -> Vec<Range<Anchor>>
626 where
627 O: text::ToPoint + text::ToOffset,
628 {
629 let buffer_id = buffer.id();
630 let buffer_snapshot = buffer.read(cx).snapshot();
631 let max_point = buffer_snapshot.max_point();
632
633 let mut range_counts = Vec::new();
634 let mut excerpt_ranges = Vec::new();
635 let mut range_iter = ranges
636 .iter()
637 .map(|range| {
638 range.start.to_point(&buffer_snapshot)..range.end.to_point(&buffer_snapshot)
639 })
640 .peekable();
641 while let Some(range) = range_iter.next() {
642 let excerpt_start = Point::new(range.start.row.saturating_sub(context_line_count), 0);
643 let mut excerpt_end =
644 Point::new(range.end.row + 1 + context_line_count, 0).min(max_point);
645 let mut ranges_in_excerpt = 1;
646
647 while let Some(next_range) = range_iter.peek() {
648 if next_range.start.row <= excerpt_end.row + context_line_count {
649 excerpt_end =
650 Point::new(next_range.end.row + 1 + context_line_count, 0).min(max_point);
651 ranges_in_excerpt += 1;
652 range_iter.next();
653 } else {
654 break;
655 }
656 }
657
658 excerpt_ranges.push(excerpt_start..excerpt_end);
659 range_counts.push(ranges_in_excerpt);
660 }
661
662 let excerpt_ids = self.push_excerpts(buffer, excerpt_ranges, cx);
663
664 let mut anchor_ranges = Vec::new();
665 let mut ranges = ranges.into_iter();
666 for (excerpt_id, range_count) in excerpt_ids.into_iter().zip(range_counts.into_iter()) {
667 anchor_ranges.extend(ranges.by_ref().take(range_count).map(|range| {
668 let start = Anchor {
669 buffer_id,
670 excerpt_id: excerpt_id.clone(),
671 text_anchor: buffer_snapshot.anchor_after(range.start),
672 };
673 let end = Anchor {
674 buffer_id,
675 excerpt_id: excerpt_id.clone(),
676 text_anchor: buffer_snapshot.anchor_after(range.end),
677 };
678 start..end
679 }))
680 }
681 anchor_ranges
682 }
683
684 pub fn insert_excerpts_after<O>(
685 &mut self,
686 prev_excerpt_id: &ExcerptId,
687 buffer: ModelHandle<Buffer>,
688 ranges: impl IntoIterator<Item = Range<O>>,
689 cx: &mut ModelContext<Self>,
690 ) -> Vec<ExcerptId>
691 where
692 O: text::ToOffset,
693 {
694 assert_eq!(self.history.transaction_depth, 0);
695 self.sync(cx);
696
697 let buffer_id = buffer.id();
698 let buffer_snapshot = buffer.read(cx).snapshot();
699
700 let mut buffers = self.buffers.borrow_mut();
701 let buffer_state = buffers.entry(buffer_id).or_insert_with(|| BufferState {
702 last_version: buffer_snapshot.version().clone(),
703 last_parse_count: buffer_snapshot.parse_count(),
704 last_selections_update_count: buffer_snapshot.selections_update_count(),
705 last_diagnostics_update_count: buffer_snapshot.diagnostics_update_count(),
706 last_file_update_count: buffer_snapshot.file_update_count(),
707 excerpts: Default::default(),
708 _subscriptions: [
709 cx.observe(&buffer, |_, _, cx| cx.notify()),
710 cx.subscribe(&buffer, Self::on_buffer_event),
711 ],
712 buffer,
713 });
714
715 let mut snapshot = self.snapshot.borrow_mut();
716 let mut cursor = snapshot.excerpts.cursor::<Option<&ExcerptId>>();
717 let mut new_excerpts = cursor.slice(&Some(prev_excerpt_id), Bias::Right, &());
718
719 let mut prev_id = ExcerptId::min();
720 let edit_start = new_excerpts.summary().text.bytes;
721 new_excerpts.update_last(
722 |excerpt| {
723 excerpt.has_trailing_newline = true;
724 prev_id = excerpt.id.clone();
725 },
726 &(),
727 );
728
729 let mut next_id = ExcerptId::max();
730 if let Some(next_excerpt) = cursor.item() {
731 next_id = next_excerpt.id.clone();
732 }
733
734 let mut ids = Vec::new();
735 let mut ranges = ranges.into_iter().peekable();
736 while let Some(range) = ranges.next() {
737 let id = ExcerptId::between(&prev_id, &next_id);
738 if let Err(ix) = buffer_state.excerpts.binary_search(&id) {
739 buffer_state.excerpts.insert(ix, id.clone());
740 }
741 let range = buffer_snapshot.anchor_before(&range.start)
742 ..buffer_snapshot.anchor_after(&range.end);
743 let excerpt = Excerpt::new(
744 id.clone(),
745 buffer_id,
746 buffer_snapshot.clone(),
747 range,
748 ranges.peek().is_some() || cursor.item().is_some(),
749 );
750 new_excerpts.push(excerpt, &());
751 prev_id = id.clone();
752 ids.push(id);
753 }
754
755 let edit_end = new_excerpts.summary().text.bytes;
756
757 let suffix = cursor.suffix(&());
758 let changed_trailing_excerpt = suffix.is_empty();
759 new_excerpts.push_tree(suffix, &());
760 drop(cursor);
761 snapshot.excerpts = new_excerpts;
762 if changed_trailing_excerpt {
763 snapshot.trailing_excerpt_update_count += 1;
764 }
765
766 self.subscriptions.publish_mut([Edit {
767 old: edit_start..edit_start,
768 new: edit_start..edit_end,
769 }]);
770
771 cx.notify();
772 ids
773 }
774
775 pub fn excerpt_ids_for_buffer(&self, buffer: &ModelHandle<Buffer>) -> Vec<ExcerptId> {
776 self.buffers
777 .borrow()
778 .get(&buffer.id())
779 .map_or(Vec::new(), |state| state.excerpts.clone())
780 }
781
782 pub fn excerpt_containing(
783 &self,
784 position: impl ToOffset,
785 cx: &AppContext,
786 ) -> Option<(ModelHandle<Buffer>, Range<text::Anchor>)> {
787 let snapshot = self.read(cx);
788 let position = position.to_offset(&snapshot);
789
790 let mut cursor = snapshot.excerpts.cursor::<usize>();
791 cursor.seek(&position, Bias::Right, &());
792 cursor.item().map(|excerpt| {
793 (
794 self.buffers
795 .borrow()
796 .get(&excerpt.buffer_id)
797 .unwrap()
798 .buffer
799 .clone(),
800 excerpt.range.clone(),
801 )
802 })
803 }
804
805 pub fn range_to_buffer_ranges<'a, T: ToOffset>(
806 &'a self,
807 range: Range<T>,
808 cx: &AppContext,
809 ) -> Vec<(ModelHandle<Buffer>, Range<usize>)> {
810 let snapshot = self.read(cx);
811 let start = range.start.to_offset(&snapshot);
812 let end = range.end.to_offset(&snapshot);
813
814 let mut result = Vec::new();
815 let mut cursor = snapshot.excerpts.cursor::<usize>();
816 cursor.seek(&start, Bias::Right, &());
817 while let Some(excerpt) = cursor.item() {
818 if *cursor.start() > end {
819 break;
820 }
821
822 let mut end_before_newline = cursor.end(&());
823 if excerpt.has_trailing_newline {
824 end_before_newline -= 1;
825 }
826 let excerpt_start = excerpt.range.start.to_offset(&excerpt.buffer);
827 let start = excerpt_start + (cmp::max(start, *cursor.start()) - *cursor.start());
828 let end = excerpt_start + (cmp::min(end, end_before_newline) - *cursor.start());
829 let buffer = self.buffers.borrow()[&excerpt.buffer_id].buffer.clone();
830 result.push((buffer, start..end));
831 cursor.next(&());
832 }
833
834 result
835 }
836
837 pub fn remove_excerpts<'a>(
838 &mut self,
839 excerpt_ids: impl IntoIterator<Item = &'a ExcerptId>,
840 cx: &mut ModelContext<Self>,
841 ) {
842 let mut buffers = self.buffers.borrow_mut();
843 let mut snapshot = self.snapshot.borrow_mut();
844 let mut new_excerpts = SumTree::new();
845 let mut cursor = snapshot.excerpts.cursor::<(Option<&ExcerptId>, usize)>();
846 let mut edits = Vec::new();
847 let mut excerpt_ids = excerpt_ids.into_iter().peekable();
848
849 while let Some(mut excerpt_id) = excerpt_ids.next() {
850 // Seek to the next excerpt to remove, preserving any preceding excerpts.
851 new_excerpts.push_tree(cursor.slice(&Some(excerpt_id), Bias::Left, &()), &());
852 if let Some(mut excerpt) = cursor.item() {
853 if excerpt.id != *excerpt_id {
854 continue;
855 }
856 let mut old_start = cursor.start().1;
857
858 // Skip over the removed excerpt.
859 loop {
860 if let Some(buffer_state) = buffers.get_mut(&excerpt.buffer_id) {
861 buffer_state.excerpts.retain(|id| id != excerpt_id);
862 if buffer_state.excerpts.is_empty() {
863 buffers.remove(&excerpt.buffer_id);
864 }
865 }
866 cursor.next(&());
867
868 // Skip over any subsequent excerpts that are also removed.
869 if let Some(&next_excerpt_id) = excerpt_ids.peek() {
870 if let Some(next_excerpt) = cursor.item() {
871 if next_excerpt.id == *next_excerpt_id {
872 excerpt = next_excerpt;
873 excerpt_id = excerpt_ids.next().unwrap();
874 continue;
875 }
876 }
877 }
878
879 break;
880 }
881
882 // When removing the last excerpt, remove the trailing newline from
883 // the previous excerpt.
884 if cursor.item().is_none() && old_start > 0 {
885 old_start -= 1;
886 new_excerpts.update_last(|e| e.has_trailing_newline = false, &());
887 }
888
889 // Push an edit for the removal of this run of excerpts.
890 let old_end = cursor.start().1;
891 let new_start = new_excerpts.summary().text.bytes;
892 edits.push(Edit {
893 old: old_start..old_end,
894 new: new_start..new_start,
895 });
896 }
897 }
898 let suffix = cursor.suffix(&());
899 let changed_trailing_excerpt = suffix.is_empty();
900 new_excerpts.push_tree(suffix, &());
901 drop(cursor);
902 snapshot.excerpts = new_excerpts;
903 if changed_trailing_excerpt {
904 snapshot.trailing_excerpt_update_count += 1;
905 }
906
907 self.subscriptions.publish_mut(edits);
908 cx.notify();
909 }
910
911 pub fn text_anchor_for_position<'a, T: ToOffset>(
912 &'a self,
913 position: T,
914 cx: &AppContext,
915 ) -> (ModelHandle<Buffer>, language::Anchor) {
916 let snapshot = self.read(cx);
917 let anchor = snapshot.anchor_before(position);
918 (
919 self.buffers.borrow()[&anchor.buffer_id].buffer.clone(),
920 anchor.text_anchor,
921 )
922 }
923
924 fn on_buffer_event(
925 &mut self,
926 _: ModelHandle<Buffer>,
927 event: &Event,
928 cx: &mut ModelContext<Self>,
929 ) {
930 cx.emit(event.clone());
931 }
932
933 pub fn format(&mut self, cx: &mut ModelContext<Self>) -> Task<Result<()>> {
934 let mut format_tasks = Vec::new();
935 for BufferState { buffer, .. } in self.buffers.borrow().values() {
936 format_tasks.push(buffer.update(cx, |buffer, cx| buffer.format(cx)));
937 }
938
939 cx.spawn(|_, _| async move {
940 for format in format_tasks {
941 format.await?;
942 }
943 Ok(())
944 })
945 }
946
947 pub fn save(&mut self, cx: &mut ModelContext<Self>) -> Task<Result<()>> {
948 let mut save_tasks = Vec::new();
949 for BufferState { buffer, .. } in self.buffers.borrow().values() {
950 save_tasks.push(buffer.update(cx, |buffer, cx| buffer.save(cx)));
951 }
952
953 cx.spawn(|_, _| async move {
954 for save in save_tasks {
955 save.await?;
956 }
957 Ok(())
958 })
959 }
960
961 pub fn is_completion_trigger<T>(&self, position: T, text: &str, cx: &AppContext) -> bool
962 where
963 T: ToOffset,
964 {
965 let mut chars = text.chars();
966 let char = if let Some(char) = chars.next() {
967 char
968 } else {
969 return false;
970 };
971 if chars.next().is_some() {
972 return false;
973 }
974
975 if char.is_alphanumeric() || char == '_' {
976 return true;
977 }
978
979 let snapshot = self.snapshot(cx);
980 let anchor = snapshot.anchor_before(position);
981 let buffer = self.buffers.borrow()[&anchor.buffer_id].buffer.clone();
982 buffer
983 .read(cx)
984 .completion_triggers()
985 .iter()
986 .any(|string| string == text)
987 }
988
989 pub fn language<'a>(&self, cx: &'a AppContext) -> Option<&'a Arc<Language>> {
990 self.buffers
991 .borrow()
992 .values()
993 .next()
994 .and_then(|state| state.buffer.read(cx).language())
995 }
996
997 pub fn file<'a>(&self, cx: &'a AppContext) -> Option<&'a dyn File> {
998 self.as_singleton()?.read(cx).file()
999 }
1000
1001 pub fn title(&self, cx: &AppContext) -> String {
1002 if let Some(title) = self.title.clone() {
1003 title
1004 } else if let Some(file) = self.file(cx) {
1005 file.file_name(cx).to_string_lossy().into()
1006 } else {
1007 "untitled".into()
1008 }
1009 }
1010
1011 #[cfg(test)]
1012 pub fn is_parsing(&self, cx: &AppContext) -> bool {
1013 self.as_singleton().unwrap().read(cx).is_parsing()
1014 }
1015
1016 fn sync(&self, cx: &AppContext) {
1017 let mut snapshot = self.snapshot.borrow_mut();
1018 let mut excerpts_to_edit = Vec::new();
1019 let mut reparsed = false;
1020 let mut diagnostics_updated = false;
1021 let mut is_dirty = false;
1022 let mut has_conflict = false;
1023 let mut buffers = self.buffers.borrow_mut();
1024 for buffer_state in buffers.values_mut() {
1025 let buffer = buffer_state.buffer.read(cx);
1026 let version = buffer.version();
1027 let parse_count = buffer.parse_count();
1028 let selections_update_count = buffer.selections_update_count();
1029 let diagnostics_update_count = buffer.diagnostics_update_count();
1030 let file_update_count = buffer.file_update_count();
1031
1032 let buffer_edited = version.changed_since(&buffer_state.last_version);
1033 let buffer_reparsed = parse_count > buffer_state.last_parse_count;
1034 let buffer_selections_updated =
1035 selections_update_count > buffer_state.last_selections_update_count;
1036 let buffer_diagnostics_updated =
1037 diagnostics_update_count > buffer_state.last_diagnostics_update_count;
1038 let buffer_file_updated = file_update_count > buffer_state.last_file_update_count;
1039 if buffer_edited
1040 || buffer_reparsed
1041 || buffer_selections_updated
1042 || buffer_diagnostics_updated
1043 || buffer_file_updated
1044 {
1045 buffer_state.last_version = version;
1046 buffer_state.last_parse_count = parse_count;
1047 buffer_state.last_selections_update_count = selections_update_count;
1048 buffer_state.last_diagnostics_update_count = diagnostics_update_count;
1049 buffer_state.last_file_update_count = file_update_count;
1050 excerpts_to_edit.extend(
1051 buffer_state
1052 .excerpts
1053 .iter()
1054 .map(|excerpt_id| (excerpt_id, buffer_state.buffer.clone(), buffer_edited)),
1055 );
1056 }
1057
1058 reparsed |= buffer_reparsed;
1059 diagnostics_updated |= buffer_diagnostics_updated;
1060 is_dirty |= buffer.is_dirty();
1061 has_conflict |= buffer.has_conflict();
1062 }
1063 if reparsed {
1064 snapshot.parse_count += 1;
1065 }
1066 if diagnostics_updated {
1067 snapshot.diagnostics_update_count += 1;
1068 }
1069 snapshot.is_dirty = is_dirty;
1070 snapshot.has_conflict = has_conflict;
1071
1072 excerpts_to_edit.sort_unstable_by_key(|(excerpt_id, _, _)| *excerpt_id);
1073
1074 let mut edits = Vec::new();
1075 let mut new_excerpts = SumTree::new();
1076 let mut cursor = snapshot.excerpts.cursor::<(Option<&ExcerptId>, usize)>();
1077
1078 for (id, buffer, buffer_edited) in excerpts_to_edit {
1079 new_excerpts.push_tree(cursor.slice(&Some(id), Bias::Left, &()), &());
1080 let old_excerpt = cursor.item().unwrap();
1081 let buffer_id = buffer.id();
1082 let buffer = buffer.read(cx);
1083
1084 let mut new_excerpt;
1085 if buffer_edited {
1086 edits.extend(
1087 buffer
1088 .edits_since_in_range::<usize>(
1089 old_excerpt.buffer.version(),
1090 old_excerpt.range.clone(),
1091 )
1092 .map(|mut edit| {
1093 let excerpt_old_start = cursor.start().1;
1094 let excerpt_new_start = new_excerpts.summary().text.bytes;
1095 edit.old.start += excerpt_old_start;
1096 edit.old.end += excerpt_old_start;
1097 edit.new.start += excerpt_new_start;
1098 edit.new.end += excerpt_new_start;
1099 edit
1100 }),
1101 );
1102
1103 new_excerpt = Excerpt::new(
1104 id.clone(),
1105 buffer_id,
1106 buffer.snapshot(),
1107 old_excerpt.range.clone(),
1108 old_excerpt.has_trailing_newline,
1109 );
1110 } else {
1111 new_excerpt = old_excerpt.clone();
1112 new_excerpt.buffer = buffer.snapshot();
1113 }
1114
1115 new_excerpts.push(new_excerpt, &());
1116 cursor.next(&());
1117 }
1118 new_excerpts.push_tree(cursor.suffix(&()), &());
1119
1120 drop(cursor);
1121 snapshot.excerpts = new_excerpts;
1122
1123 self.subscriptions.publish(edits);
1124 }
1125}
1126
1127#[cfg(any(test, feature = "test-support"))]
1128impl MultiBuffer {
1129 pub fn randomly_edit(
1130 &mut self,
1131 rng: &mut impl rand::Rng,
1132 count: usize,
1133 cx: &mut ModelContext<Self>,
1134 ) {
1135 use text::RandomCharIter;
1136
1137 let snapshot = self.read(cx);
1138 let mut old_ranges: Vec<Range<usize>> = Vec::new();
1139 for _ in 0..count {
1140 let last_end = old_ranges.last().map_or(0, |last_range| last_range.end + 1);
1141 if last_end > snapshot.len() {
1142 break;
1143 }
1144 let end_ix = snapshot.clip_offset(rng.gen_range(0..=last_end), Bias::Right);
1145 let start_ix = snapshot.clip_offset(rng.gen_range(0..=end_ix), Bias::Left);
1146 old_ranges.push(start_ix..end_ix);
1147 }
1148 let new_text_len = rng.gen_range(0..10);
1149 let new_text: String = RandomCharIter::new(&mut *rng).take(new_text_len).collect();
1150 log::info!("mutating multi-buffer at {:?}: {:?}", old_ranges, new_text);
1151 drop(snapshot);
1152
1153 self.edit(old_ranges.iter().cloned(), new_text.as_str(), cx);
1154 }
1155
1156 pub fn randomly_edit_excerpts(
1157 &mut self,
1158 rng: &mut impl rand::Rng,
1159 mutation_count: usize,
1160 cx: &mut ModelContext<Self>,
1161 ) {
1162 use rand::prelude::*;
1163 use std::env;
1164 use text::RandomCharIter;
1165
1166 let max_excerpts = env::var("MAX_EXCERPTS")
1167 .map(|i| i.parse().expect("invalid `MAX_EXCERPTS` variable"))
1168 .unwrap_or(5);
1169
1170 let mut buffers = Vec::new();
1171 for _ in 0..mutation_count {
1172 let excerpt_ids = self
1173 .buffers
1174 .borrow()
1175 .values()
1176 .flat_map(|b| &b.excerpts)
1177 .cloned()
1178 .collect::<Vec<_>>();
1179 if excerpt_ids.len() == 0 || (rng.gen() && excerpt_ids.len() < max_excerpts) {
1180 let buffer_handle = if rng.gen() || self.buffers.borrow().is_empty() {
1181 let text = RandomCharIter::new(&mut *rng).take(10).collect::<String>();
1182 buffers.push(cx.add_model(|cx| Buffer::new(0, text, cx)));
1183 let buffer = buffers.last().unwrap();
1184 log::info!(
1185 "Creating new buffer {} with text: {:?}",
1186 buffer.id(),
1187 buffer.read(cx).text()
1188 );
1189 buffers.last().unwrap().clone()
1190 } else {
1191 self.buffers
1192 .borrow()
1193 .values()
1194 .choose(rng)
1195 .unwrap()
1196 .buffer
1197 .clone()
1198 };
1199
1200 let buffer = buffer_handle.read(cx);
1201 let end_ix = buffer.clip_offset(rng.gen_range(0..=buffer.len()), Bias::Right);
1202 let start_ix = buffer.clip_offset(rng.gen_range(0..=end_ix), Bias::Left);
1203 log::info!(
1204 "Inserting excerpt from buffer {} and range {:?}: {:?}",
1205 buffer_handle.id(),
1206 start_ix..end_ix,
1207 &buffer.text()[start_ix..end_ix]
1208 );
1209
1210 let excerpt_id = self.push_excerpts(buffer_handle.clone(), [start_ix..end_ix], cx);
1211 log::info!("Inserted with id: {:?}", excerpt_id);
1212 } else {
1213 let remove_count = rng.gen_range(1..=excerpt_ids.len());
1214 let mut excerpts_to_remove = excerpt_ids
1215 .choose_multiple(rng, remove_count)
1216 .cloned()
1217 .collect::<Vec<_>>();
1218 excerpts_to_remove.sort();
1219 log::info!("Removing excerpts {:?}", excerpts_to_remove);
1220 self.remove_excerpts(&excerpts_to_remove, cx);
1221 }
1222 }
1223 }
1224
1225 pub fn randomly_mutate(
1226 &mut self,
1227 rng: &mut impl rand::Rng,
1228 mutation_count: usize,
1229 cx: &mut ModelContext<Self>,
1230 ) {
1231 if rng.gen_bool(0.7) || self.singleton {
1232 self.randomly_edit(rng, mutation_count, cx);
1233 } else {
1234 self.randomly_edit_excerpts(rng, mutation_count, cx);
1235 }
1236 }
1237}
1238
1239impl Entity for MultiBuffer {
1240 type Event = language::Event;
1241}
1242
1243impl MultiBufferSnapshot {
1244 pub fn text(&self) -> String {
1245 self.chunks(0..self.len(), false)
1246 .map(|chunk| chunk.text)
1247 .collect()
1248 }
1249
1250 pub fn reversed_chars_at<'a, T: ToOffset>(
1251 &'a self,
1252 position: T,
1253 ) -> impl Iterator<Item = char> + 'a {
1254 let mut offset = position.to_offset(self);
1255 let mut cursor = self.excerpts.cursor::<usize>();
1256 cursor.seek(&offset, Bias::Left, &());
1257 let mut excerpt_chunks = cursor.item().map(|excerpt| {
1258 let end_before_footer = cursor.start() + excerpt.text_summary.bytes;
1259 let start = excerpt.range.start.to_offset(&excerpt.buffer);
1260 let end = start + (cmp::min(offset, end_before_footer) - cursor.start());
1261 excerpt.buffer.reversed_chunks_in_range(start..end)
1262 });
1263 iter::from_fn(move || {
1264 if offset == *cursor.start() {
1265 cursor.prev(&());
1266 let excerpt = cursor.item()?;
1267 excerpt_chunks = Some(
1268 excerpt
1269 .buffer
1270 .reversed_chunks_in_range(excerpt.range.clone()),
1271 );
1272 }
1273
1274 let excerpt = cursor.item().unwrap();
1275 if offset == cursor.end(&()) && excerpt.has_trailing_newline {
1276 offset -= 1;
1277 Some("\n")
1278 } else {
1279 let chunk = excerpt_chunks.as_mut().unwrap().next().unwrap();
1280 offset -= chunk.len();
1281 Some(chunk)
1282 }
1283 })
1284 .flat_map(|c| c.chars().rev())
1285 }
1286
1287 pub fn chars_at<'a, T: ToOffset>(&'a self, position: T) -> impl Iterator<Item = char> + 'a {
1288 let offset = position.to_offset(self);
1289 self.text_for_range(offset..self.len())
1290 .flat_map(|chunk| chunk.chars())
1291 }
1292
1293 pub fn text_for_range<'a, T: ToOffset>(
1294 &'a self,
1295 range: Range<T>,
1296 ) -> impl Iterator<Item = &'a str> {
1297 self.chunks(range, false).map(|chunk| chunk.text)
1298 }
1299
1300 pub fn is_line_blank(&self, row: u32) -> bool {
1301 self.text_for_range(Point::new(row, 0)..Point::new(row, self.line_len(row)))
1302 .all(|chunk| chunk.matches(|c: char| !c.is_whitespace()).next().is_none())
1303 }
1304
1305 pub fn contains_str_at<T>(&self, position: T, needle: &str) -> bool
1306 where
1307 T: ToOffset,
1308 {
1309 let position = position.to_offset(self);
1310 position == self.clip_offset(position, Bias::Left)
1311 && self
1312 .bytes_in_range(position..self.len())
1313 .flatten()
1314 .copied()
1315 .take(needle.len())
1316 .eq(needle.bytes())
1317 }
1318
1319 pub fn surrounding_word<T: ToOffset>(&self, start: T) -> (Range<usize>, Option<CharKind>) {
1320 let mut start = start.to_offset(self);
1321 let mut end = start;
1322 let mut next_chars = self.chars_at(start).peekable();
1323 let mut prev_chars = self.reversed_chars_at(start).peekable();
1324 let word_kind = cmp::max(
1325 prev_chars.peek().copied().map(char_kind),
1326 next_chars.peek().copied().map(char_kind),
1327 );
1328
1329 for ch in prev_chars {
1330 if Some(char_kind(ch)) == word_kind {
1331 start -= ch.len_utf8();
1332 } else {
1333 break;
1334 }
1335 }
1336
1337 for ch in next_chars {
1338 if Some(char_kind(ch)) == word_kind {
1339 end += ch.len_utf8();
1340 } else {
1341 break;
1342 }
1343 }
1344
1345 (start..end, word_kind)
1346 }
1347
1348 fn as_singleton(&self) -> Option<&Excerpt> {
1349 if self.singleton {
1350 self.excerpts.iter().next()
1351 } else {
1352 None
1353 }
1354 }
1355
1356 pub fn len(&self) -> usize {
1357 self.excerpts.summary().text.bytes
1358 }
1359
1360 pub fn max_buffer_row(&self) -> u32 {
1361 self.excerpts.summary().max_buffer_row
1362 }
1363
1364 pub fn clip_offset(&self, offset: usize, bias: Bias) -> usize {
1365 if let Some(excerpt) = self.as_singleton() {
1366 return excerpt.buffer.clip_offset(offset, bias);
1367 }
1368
1369 let mut cursor = self.excerpts.cursor::<usize>();
1370 cursor.seek(&offset, Bias::Right, &());
1371 let overshoot = if let Some(excerpt) = cursor.item() {
1372 let excerpt_start = excerpt.range.start.to_offset(&excerpt.buffer);
1373 let buffer_offset = excerpt
1374 .buffer
1375 .clip_offset(excerpt_start + (offset - cursor.start()), bias);
1376 buffer_offset.saturating_sub(excerpt_start)
1377 } else {
1378 0
1379 };
1380 cursor.start() + overshoot
1381 }
1382
1383 pub fn clip_point(&self, point: Point, bias: Bias) -> Point {
1384 if let Some(excerpt) = self.as_singleton() {
1385 return excerpt.buffer.clip_point(point, bias);
1386 }
1387
1388 let mut cursor = self.excerpts.cursor::<Point>();
1389 cursor.seek(&point, Bias::Right, &());
1390 let overshoot = if let Some(excerpt) = cursor.item() {
1391 let excerpt_start = excerpt.range.start.to_point(&excerpt.buffer);
1392 let buffer_point = excerpt
1393 .buffer
1394 .clip_point(excerpt_start + (point - cursor.start()), bias);
1395 buffer_point.saturating_sub(excerpt_start)
1396 } else {
1397 Point::zero()
1398 };
1399 *cursor.start() + overshoot
1400 }
1401
1402 pub fn clip_point_utf16(&self, point: PointUtf16, bias: Bias) -> PointUtf16 {
1403 if let Some(excerpt) = self.as_singleton() {
1404 return excerpt.buffer.clip_point_utf16(point, bias);
1405 }
1406
1407 let mut cursor = self.excerpts.cursor::<PointUtf16>();
1408 cursor.seek(&point, Bias::Right, &());
1409 let overshoot = if let Some(excerpt) = cursor.item() {
1410 let excerpt_start = excerpt
1411 .buffer
1412 .offset_to_point_utf16(excerpt.range.start.to_offset(&excerpt.buffer));
1413 let buffer_point = excerpt
1414 .buffer
1415 .clip_point_utf16(excerpt_start + (point - cursor.start()), bias);
1416 buffer_point.saturating_sub(excerpt_start)
1417 } else {
1418 PointUtf16::zero()
1419 };
1420 *cursor.start() + overshoot
1421 }
1422
1423 pub fn bytes_in_range<'a, T: ToOffset>(&'a self, range: Range<T>) -> MultiBufferBytes<'a> {
1424 let range = range.start.to_offset(self)..range.end.to_offset(self);
1425 let mut excerpts = self.excerpts.cursor::<usize>();
1426 excerpts.seek(&range.start, Bias::Right, &());
1427
1428 let mut chunk = &[][..];
1429 let excerpt_bytes = if let Some(excerpt) = excerpts.item() {
1430 let mut excerpt_bytes = excerpt
1431 .bytes_in_range(range.start - excerpts.start()..range.end - excerpts.start());
1432 chunk = excerpt_bytes.next().unwrap_or(&[][..]);
1433 Some(excerpt_bytes)
1434 } else {
1435 None
1436 };
1437
1438 MultiBufferBytes {
1439 range,
1440 excerpts,
1441 excerpt_bytes,
1442 chunk,
1443 }
1444 }
1445
1446 pub fn buffer_rows<'a>(&'a self, start_row: u32) -> MultiBufferRows<'a> {
1447 let mut result = MultiBufferRows {
1448 buffer_row_range: 0..0,
1449 excerpts: self.excerpts.cursor(),
1450 };
1451 result.seek(start_row);
1452 result
1453 }
1454
1455 pub fn chunks<'a, T: ToOffset>(
1456 &'a self,
1457 range: Range<T>,
1458 language_aware: bool,
1459 ) -> MultiBufferChunks<'a> {
1460 let range = range.start.to_offset(self)..range.end.to_offset(self);
1461 let mut chunks = MultiBufferChunks {
1462 range: range.clone(),
1463 excerpts: self.excerpts.cursor(),
1464 excerpt_chunks: None,
1465 language_aware,
1466 };
1467 chunks.seek(range.start);
1468 chunks
1469 }
1470
1471 pub fn offset_to_point(&self, offset: usize) -> Point {
1472 if let Some(excerpt) = self.as_singleton() {
1473 return excerpt.buffer.offset_to_point(offset);
1474 }
1475
1476 let mut cursor = self.excerpts.cursor::<(usize, Point)>();
1477 cursor.seek(&offset, Bias::Right, &());
1478 if let Some(excerpt) = cursor.item() {
1479 let (start_offset, start_point) = cursor.start();
1480 let overshoot = offset - start_offset;
1481 let excerpt_start_offset = excerpt.range.start.to_offset(&excerpt.buffer);
1482 let excerpt_start_point = excerpt.range.start.to_point(&excerpt.buffer);
1483 let buffer_point = excerpt
1484 .buffer
1485 .offset_to_point(excerpt_start_offset + overshoot);
1486 *start_point + (buffer_point - excerpt_start_point)
1487 } else {
1488 self.excerpts.summary().text.lines
1489 }
1490 }
1491
1492 pub fn offset_to_point_utf16(&self, offset: usize) -> PointUtf16 {
1493 if let Some(excerpt) = self.as_singleton() {
1494 return excerpt.buffer.offset_to_point_utf16(offset);
1495 }
1496
1497 let mut cursor = self.excerpts.cursor::<(usize, PointUtf16)>();
1498 cursor.seek(&offset, Bias::Right, &());
1499 if let Some(excerpt) = cursor.item() {
1500 let (start_offset, start_point) = cursor.start();
1501 let overshoot = offset - start_offset;
1502 let excerpt_start_offset = excerpt.range.start.to_offset(&excerpt.buffer);
1503 let excerpt_start_point = excerpt.range.start.to_point_utf16(&excerpt.buffer);
1504 let buffer_point = excerpt
1505 .buffer
1506 .offset_to_point_utf16(excerpt_start_offset + overshoot);
1507 *start_point + (buffer_point - excerpt_start_point)
1508 } else {
1509 self.excerpts.summary().text.lines_utf16
1510 }
1511 }
1512
1513 pub fn point_to_point_utf16(&self, point: Point) -> PointUtf16 {
1514 if let Some(excerpt) = self.as_singleton() {
1515 return excerpt.buffer.point_to_point_utf16(point);
1516 }
1517
1518 let mut cursor = self.excerpts.cursor::<(Point, PointUtf16)>();
1519 cursor.seek(&point, Bias::Right, &());
1520 if let Some(excerpt) = cursor.item() {
1521 let (start_offset, start_point) = cursor.start();
1522 let overshoot = point - start_offset;
1523 let excerpt_start_point = excerpt.range.start.to_point(&excerpt.buffer);
1524 let excerpt_start_point_utf16 = excerpt.range.start.to_point_utf16(&excerpt.buffer);
1525 let buffer_point = excerpt
1526 .buffer
1527 .point_to_point_utf16(excerpt_start_point + overshoot);
1528 *start_point + (buffer_point - excerpt_start_point_utf16)
1529 } else {
1530 self.excerpts.summary().text.lines_utf16
1531 }
1532 }
1533
1534 pub fn point_to_offset(&self, point: Point) -> usize {
1535 if let Some(excerpt) = self.as_singleton() {
1536 return excerpt.buffer.point_to_offset(point);
1537 }
1538
1539 let mut cursor = self.excerpts.cursor::<(Point, usize)>();
1540 cursor.seek(&point, Bias::Right, &());
1541 if let Some(excerpt) = cursor.item() {
1542 let (start_point, start_offset) = cursor.start();
1543 let overshoot = point - start_point;
1544 let excerpt_start_offset = excerpt.range.start.to_offset(&excerpt.buffer);
1545 let excerpt_start_point = excerpt.range.start.to_point(&excerpt.buffer);
1546 let buffer_offset = excerpt
1547 .buffer
1548 .point_to_offset(excerpt_start_point + overshoot);
1549 *start_offset + buffer_offset - excerpt_start_offset
1550 } else {
1551 self.excerpts.summary().text.bytes
1552 }
1553 }
1554
1555 pub fn point_utf16_to_offset(&self, point: PointUtf16) -> usize {
1556 if let Some(excerpt) = self.as_singleton() {
1557 return excerpt.buffer.point_utf16_to_offset(point);
1558 }
1559
1560 let mut cursor = self.excerpts.cursor::<(PointUtf16, usize)>();
1561 cursor.seek(&point, Bias::Right, &());
1562 if let Some(excerpt) = cursor.item() {
1563 let (start_point, start_offset) = cursor.start();
1564 let overshoot = point - start_point;
1565 let excerpt_start_offset = excerpt.range.start.to_offset(&excerpt.buffer);
1566 let excerpt_start_point = excerpt
1567 .buffer
1568 .offset_to_point_utf16(excerpt.range.start.to_offset(&excerpt.buffer));
1569 let buffer_offset = excerpt
1570 .buffer
1571 .point_utf16_to_offset(excerpt_start_point + overshoot);
1572 *start_offset + (buffer_offset - excerpt_start_offset)
1573 } else {
1574 self.excerpts.summary().text.bytes
1575 }
1576 }
1577
1578 pub fn indent_column_for_line(&self, row: u32) -> u32 {
1579 if let Some((buffer, range)) = self.buffer_line_for_row(row) {
1580 buffer
1581 .indent_column_for_line(range.start.row)
1582 .min(range.end.column)
1583 .saturating_sub(range.start.column)
1584 } else {
1585 0
1586 }
1587 }
1588
1589 pub fn line_len(&self, row: u32) -> u32 {
1590 if let Some((_, range)) = self.buffer_line_for_row(row) {
1591 range.end.column - range.start.column
1592 } else {
1593 0
1594 }
1595 }
1596
1597 fn buffer_line_for_row(&self, row: u32) -> Option<(&BufferSnapshot, Range<Point>)> {
1598 let mut cursor = self.excerpts.cursor::<Point>();
1599 cursor.seek(&Point::new(row, 0), Bias::Right, &());
1600 if let Some(excerpt) = cursor.item() {
1601 let overshoot = row - cursor.start().row;
1602 let excerpt_start = excerpt.range.start.to_point(&excerpt.buffer);
1603 let excerpt_end = excerpt.range.end.to_point(&excerpt.buffer);
1604 let buffer_row = excerpt_start.row + overshoot;
1605 let line_start = Point::new(buffer_row, 0);
1606 let line_end = Point::new(buffer_row, excerpt.buffer.line_len(buffer_row));
1607 return Some((
1608 &excerpt.buffer,
1609 line_start.max(excerpt_start)..line_end.min(excerpt_end),
1610 ));
1611 }
1612 None
1613 }
1614
1615 pub fn max_point(&self) -> Point {
1616 self.text_summary().lines
1617 }
1618
1619 pub fn text_summary(&self) -> TextSummary {
1620 self.excerpts.summary().text
1621 }
1622
1623 pub fn text_summary_for_range<'a, D, O>(&'a self, range: Range<O>) -> D
1624 where
1625 D: TextDimension,
1626 O: ToOffset,
1627 {
1628 let mut summary = D::default();
1629 let mut range = range.start.to_offset(self)..range.end.to_offset(self);
1630 let mut cursor = self.excerpts.cursor::<usize>();
1631 cursor.seek(&range.start, Bias::Right, &());
1632 if let Some(excerpt) = cursor.item() {
1633 let mut end_before_newline = cursor.end(&());
1634 if excerpt.has_trailing_newline {
1635 end_before_newline -= 1;
1636 }
1637
1638 let excerpt_start = excerpt.range.start.to_offset(&excerpt.buffer);
1639 let start_in_excerpt = excerpt_start + (range.start - cursor.start());
1640 let end_in_excerpt =
1641 excerpt_start + (cmp::min(end_before_newline, range.end) - cursor.start());
1642 summary.add_assign(
1643 &excerpt
1644 .buffer
1645 .text_summary_for_range(start_in_excerpt..end_in_excerpt),
1646 );
1647
1648 if range.end > end_before_newline {
1649 summary.add_assign(&D::from_text_summary(&TextSummary {
1650 bytes: 1,
1651 lines: Point::new(1 as u32, 0),
1652 lines_utf16: PointUtf16::new(1 as u32, 0),
1653 first_line_chars: 0,
1654 last_line_chars: 0,
1655 longest_row: 0,
1656 longest_row_chars: 0,
1657 }));
1658 }
1659
1660 cursor.next(&());
1661 }
1662
1663 if range.end > *cursor.start() {
1664 summary.add_assign(&D::from_text_summary(&cursor.summary::<_, TextSummary>(
1665 &range.end,
1666 Bias::Right,
1667 &(),
1668 )));
1669 if let Some(excerpt) = cursor.item() {
1670 range.end = cmp::max(*cursor.start(), range.end);
1671
1672 let excerpt_start = excerpt.range.start.to_offset(&excerpt.buffer);
1673 let end_in_excerpt = excerpt_start + (range.end - cursor.start());
1674 summary.add_assign(
1675 &excerpt
1676 .buffer
1677 .text_summary_for_range(excerpt_start..end_in_excerpt),
1678 );
1679 }
1680 }
1681
1682 summary
1683 }
1684
1685 pub fn summary_for_anchor<D>(&self, anchor: &Anchor) -> D
1686 where
1687 D: TextDimension + Ord + Sub<D, Output = D>,
1688 {
1689 let mut cursor = self.excerpts.cursor::<ExcerptSummary>();
1690 cursor.seek(&Some(&anchor.excerpt_id), Bias::Left, &());
1691 if cursor.item().is_none() {
1692 cursor.next(&());
1693 }
1694
1695 let mut position = D::from_text_summary(&cursor.start().text);
1696 if let Some(excerpt) = cursor.item() {
1697 if excerpt.id == anchor.excerpt_id && excerpt.buffer_id == anchor.buffer_id {
1698 let excerpt_buffer_start = excerpt.range.start.summary::<D>(&excerpt.buffer);
1699 let excerpt_buffer_end = excerpt.range.end.summary::<D>(&excerpt.buffer);
1700 let buffer_position = cmp::min(
1701 excerpt_buffer_end,
1702 anchor.text_anchor.summary::<D>(&excerpt.buffer),
1703 );
1704 if buffer_position > excerpt_buffer_start {
1705 position.add_assign(&(buffer_position - excerpt_buffer_start));
1706 }
1707 }
1708 }
1709 position
1710 }
1711
1712 pub fn summaries_for_anchors<'a, D, I>(&'a self, anchors: I) -> Vec<D>
1713 where
1714 D: TextDimension + Ord + Sub<D, Output = D>,
1715 I: 'a + IntoIterator<Item = &'a Anchor>,
1716 {
1717 if let Some(excerpt) = self.as_singleton() {
1718 return excerpt
1719 .buffer
1720 .summaries_for_anchors(anchors.into_iter().map(|a| &a.text_anchor))
1721 .collect();
1722 }
1723
1724 let mut anchors = anchors.into_iter().peekable();
1725 let mut cursor = self.excerpts.cursor::<ExcerptSummary>();
1726 let mut summaries = Vec::new();
1727 while let Some(anchor) = anchors.peek() {
1728 let excerpt_id = &anchor.excerpt_id;
1729 let buffer_id = anchor.buffer_id;
1730 let excerpt_anchors = iter::from_fn(|| {
1731 let anchor = anchors.peek()?;
1732 if anchor.excerpt_id == *excerpt_id && anchor.buffer_id == buffer_id {
1733 Some(&anchors.next().unwrap().text_anchor)
1734 } else {
1735 None
1736 }
1737 });
1738
1739 cursor.seek_forward(&Some(excerpt_id), Bias::Left, &());
1740 if cursor.item().is_none() {
1741 cursor.next(&());
1742 }
1743
1744 let position = D::from_text_summary(&cursor.start().text);
1745 if let Some(excerpt) = cursor.item() {
1746 if excerpt.id == *excerpt_id && excerpt.buffer_id == buffer_id {
1747 let excerpt_buffer_start = excerpt.range.start.summary::<D>(&excerpt.buffer);
1748 let excerpt_buffer_end = excerpt.range.end.summary::<D>(&excerpt.buffer);
1749 summaries.extend(
1750 excerpt
1751 .buffer
1752 .summaries_for_anchors::<D, _>(excerpt_anchors)
1753 .map(move |summary| {
1754 let summary = cmp::min(excerpt_buffer_end.clone(), summary);
1755 let mut position = position.clone();
1756 let excerpt_buffer_start = excerpt_buffer_start.clone();
1757 if summary > excerpt_buffer_start {
1758 position.add_assign(&(summary - excerpt_buffer_start));
1759 }
1760 position
1761 }),
1762 );
1763 continue;
1764 }
1765 }
1766
1767 summaries.extend(excerpt_anchors.map(|_| position.clone()));
1768 }
1769
1770 summaries
1771 }
1772
1773 pub fn refresh_anchors<'a, I>(&'a self, anchors: I) -> Vec<(usize, Anchor, bool)>
1774 where
1775 I: 'a + IntoIterator<Item = &'a Anchor>,
1776 {
1777 let mut anchors = anchors.into_iter().enumerate().peekable();
1778 let mut cursor = self.excerpts.cursor::<Option<&ExcerptId>>();
1779 let mut result = Vec::new();
1780 while let Some((_, anchor)) = anchors.peek() {
1781 let old_excerpt_id = &anchor.excerpt_id;
1782
1783 // Find the location where this anchor's excerpt should be.
1784 cursor.seek_forward(&Some(old_excerpt_id), Bias::Left, &());
1785 if cursor.item().is_none() {
1786 cursor.next(&());
1787 }
1788
1789 let next_excerpt = cursor.item();
1790 let prev_excerpt = cursor.prev_item();
1791
1792 // Process all of the anchors for this excerpt.
1793 while let Some((_, anchor)) = anchors.peek() {
1794 if anchor.excerpt_id != *old_excerpt_id {
1795 break;
1796 }
1797 let mut kept_position = false;
1798 let (anchor_ix, anchor) = anchors.next().unwrap();
1799 let mut anchor = anchor.clone();
1800
1801 // Leave min and max anchors unchanged.
1802 if *old_excerpt_id == ExcerptId::max() || *old_excerpt_id == ExcerptId::min() {
1803 kept_position = true;
1804 }
1805 // If the old excerpt still exists at this location, then leave
1806 // the anchor unchanged.
1807 else if next_excerpt.map_or(false, |excerpt| {
1808 excerpt.id == *old_excerpt_id && excerpt.contains(&anchor)
1809 }) {
1810 kept_position = true;
1811 }
1812 // If the old excerpt no longer exists at this location, then attempt to
1813 // find an equivalent position for this anchor in an adjacent excerpt.
1814 else {
1815 for excerpt in [next_excerpt, prev_excerpt].iter().filter_map(|e| *e) {
1816 if excerpt.contains(&anchor) {
1817 anchor.excerpt_id = excerpt.id.clone();
1818 kept_position = true;
1819 break;
1820 }
1821 }
1822 }
1823 // If there's no adjacent excerpt that contains the anchor's position,
1824 // then report that the anchor has lost its position.
1825 if !kept_position {
1826 anchor = if let Some(excerpt) = next_excerpt {
1827 let mut text_anchor = excerpt
1828 .range
1829 .start
1830 .bias(anchor.text_anchor.bias, &excerpt.buffer);
1831 if text_anchor
1832 .cmp(&excerpt.range.end, &excerpt.buffer)
1833 .unwrap()
1834 .is_gt()
1835 {
1836 text_anchor = excerpt.range.end.clone();
1837 }
1838 Anchor {
1839 buffer_id: excerpt.buffer_id,
1840 excerpt_id: excerpt.id.clone(),
1841 text_anchor,
1842 }
1843 } else if let Some(excerpt) = prev_excerpt {
1844 let mut text_anchor = excerpt
1845 .range
1846 .end
1847 .bias(anchor.text_anchor.bias, &excerpt.buffer);
1848 if text_anchor
1849 .cmp(&excerpt.range.start, &excerpt.buffer)
1850 .unwrap()
1851 .is_lt()
1852 {
1853 text_anchor = excerpt.range.start.clone();
1854 }
1855 Anchor {
1856 buffer_id: excerpt.buffer_id,
1857 excerpt_id: excerpt.id.clone(),
1858 text_anchor,
1859 }
1860 } else if anchor.text_anchor.bias == Bias::Left {
1861 Anchor::min()
1862 } else {
1863 Anchor::max()
1864 };
1865 }
1866
1867 result.push((anchor_ix, anchor, kept_position));
1868 }
1869 }
1870 result.sort_unstable_by(|a, b| a.1.cmp(&b.1, self).unwrap());
1871 result
1872 }
1873
1874 pub fn anchor_before<T: ToOffset>(&self, position: T) -> Anchor {
1875 self.anchor_at(position, Bias::Left)
1876 }
1877
1878 pub fn anchor_after<T: ToOffset>(&self, position: T) -> Anchor {
1879 self.anchor_at(position, Bias::Right)
1880 }
1881
1882 pub fn anchor_at<T: ToOffset>(&self, position: T, mut bias: Bias) -> Anchor {
1883 let offset = position.to_offset(self);
1884 if let Some(excerpt) = self.as_singleton() {
1885 return Anchor {
1886 buffer_id: excerpt.buffer_id,
1887 excerpt_id: excerpt.id.clone(),
1888 text_anchor: excerpt.buffer.anchor_at(offset, bias),
1889 };
1890 }
1891
1892 let mut cursor = self.excerpts.cursor::<(usize, Option<&ExcerptId>)>();
1893 cursor.seek(&offset, Bias::Right, &());
1894 if cursor.item().is_none() && offset == cursor.start().0 && bias == Bias::Left {
1895 cursor.prev(&());
1896 }
1897 if let Some(excerpt) = cursor.item() {
1898 let mut overshoot = offset.saturating_sub(cursor.start().0);
1899 if excerpt.has_trailing_newline && offset == cursor.end(&()).0 {
1900 overshoot -= 1;
1901 bias = Bias::Right;
1902 }
1903
1904 let buffer_start = excerpt.range.start.to_offset(&excerpt.buffer);
1905 let text_anchor =
1906 excerpt.clip_anchor(excerpt.buffer.anchor_at(buffer_start + overshoot, bias));
1907 Anchor {
1908 buffer_id: excerpt.buffer_id,
1909 excerpt_id: excerpt.id.clone(),
1910 text_anchor,
1911 }
1912 } else if offset == 0 && bias == Bias::Left {
1913 Anchor::min()
1914 } else {
1915 Anchor::max()
1916 }
1917 }
1918
1919 pub fn anchor_in_excerpt(&self, excerpt_id: ExcerptId, text_anchor: text::Anchor) -> Anchor {
1920 let mut cursor = self.excerpts.cursor::<Option<&ExcerptId>>();
1921 cursor.seek(&Some(&excerpt_id), Bias::Left, &());
1922 if let Some(excerpt) = cursor.item() {
1923 if excerpt.id == excerpt_id {
1924 let text_anchor = excerpt.clip_anchor(text_anchor);
1925 drop(cursor);
1926 return Anchor {
1927 buffer_id: excerpt.buffer_id,
1928 excerpt_id,
1929 text_anchor,
1930 };
1931 }
1932 }
1933 panic!("excerpt not found");
1934 }
1935
1936 pub fn can_resolve(&self, anchor: &Anchor) -> bool {
1937 if anchor.excerpt_id == ExcerptId::min() || anchor.excerpt_id == ExcerptId::max() {
1938 true
1939 } else if let Some((buffer_id, buffer_snapshot)) =
1940 self.buffer_snapshot_for_excerpt(&anchor.excerpt_id)
1941 {
1942 anchor.buffer_id == buffer_id && buffer_snapshot.can_resolve(&anchor.text_anchor)
1943 } else {
1944 false
1945 }
1946 }
1947
1948 pub fn excerpt_boundaries_in_range<'a, R, T>(
1949 &'a self,
1950 range: R,
1951 ) -> impl Iterator<Item = ExcerptBoundary> + 'a
1952 where
1953 R: RangeBounds<T>,
1954 T: ToOffset,
1955 {
1956 let start_offset;
1957 let start = match range.start_bound() {
1958 Bound::Included(start) => {
1959 start_offset = start.to_offset(self);
1960 Bound::Included(start_offset)
1961 }
1962 Bound::Excluded(start) => {
1963 start_offset = start.to_offset(self);
1964 Bound::Excluded(start_offset)
1965 }
1966 Bound::Unbounded => {
1967 start_offset = 0;
1968 Bound::Unbounded
1969 }
1970 };
1971 let end = match range.end_bound() {
1972 Bound::Included(end) => Bound::Included(end.to_offset(self)),
1973 Bound::Excluded(end) => Bound::Excluded(end.to_offset(self)),
1974 Bound::Unbounded => Bound::Unbounded,
1975 };
1976 let bounds = (start, end);
1977
1978 let mut cursor = self.excerpts.cursor::<(usize, Point)>();
1979 cursor.seek(&start_offset, Bias::Right, &());
1980 if cursor.item().is_none() {
1981 cursor.prev(&());
1982 }
1983 if !bounds.contains(&cursor.start().0) {
1984 cursor.next(&());
1985 }
1986
1987 let mut prev_buffer_id = cursor.prev_item().map(|excerpt| excerpt.buffer_id);
1988 std::iter::from_fn(move || {
1989 if self.singleton {
1990 None
1991 } else if bounds.contains(&cursor.start().0) {
1992 let excerpt = cursor.item()?;
1993 let starts_new_buffer = Some(excerpt.buffer_id) != prev_buffer_id;
1994 let boundary = ExcerptBoundary {
1995 row: cursor.start().1.row,
1996 buffer: excerpt.buffer.clone(),
1997 range: excerpt.range.clone(),
1998 starts_new_buffer,
1999 };
2000
2001 prev_buffer_id = Some(excerpt.buffer_id);
2002 cursor.next(&());
2003 Some(boundary)
2004 } else {
2005 None
2006 }
2007 })
2008 }
2009
2010 pub fn parse_count(&self) -> usize {
2011 self.parse_count
2012 }
2013
2014 pub fn enclosing_bracket_ranges<T: ToOffset>(
2015 &self,
2016 range: Range<T>,
2017 ) -> Option<(Range<usize>, Range<usize>)> {
2018 let range = range.start.to_offset(self)..range.end.to_offset(self);
2019
2020 let mut cursor = self.excerpts.cursor::<usize>();
2021 cursor.seek(&range.start, Bias::Right, &());
2022 let start_excerpt = cursor.item();
2023
2024 cursor.seek(&range.end, Bias::Right, &());
2025 let end_excerpt = cursor.item();
2026
2027 start_excerpt
2028 .zip(end_excerpt)
2029 .and_then(|(start_excerpt, end_excerpt)| {
2030 if start_excerpt.id != end_excerpt.id {
2031 return None;
2032 }
2033
2034 let excerpt_buffer_start =
2035 start_excerpt.range.start.to_offset(&start_excerpt.buffer);
2036 let excerpt_buffer_end = excerpt_buffer_start + start_excerpt.text_summary.bytes;
2037
2038 let start_in_buffer =
2039 excerpt_buffer_start + range.start.saturating_sub(*cursor.start());
2040 let end_in_buffer =
2041 excerpt_buffer_start + range.end.saturating_sub(*cursor.start());
2042 let (mut start_bracket_range, mut end_bracket_range) = start_excerpt
2043 .buffer
2044 .enclosing_bracket_ranges(start_in_buffer..end_in_buffer)?;
2045
2046 if start_bracket_range.start >= excerpt_buffer_start
2047 && end_bracket_range.end < excerpt_buffer_end
2048 {
2049 start_bracket_range.start =
2050 cursor.start() + (start_bracket_range.start - excerpt_buffer_start);
2051 start_bracket_range.end =
2052 cursor.start() + (start_bracket_range.end - excerpt_buffer_start);
2053 end_bracket_range.start =
2054 cursor.start() + (end_bracket_range.start - excerpt_buffer_start);
2055 end_bracket_range.end =
2056 cursor.start() + (end_bracket_range.end - excerpt_buffer_start);
2057 Some((start_bracket_range, end_bracket_range))
2058 } else {
2059 None
2060 }
2061 })
2062 }
2063
2064 pub fn diagnostics_update_count(&self) -> usize {
2065 self.diagnostics_update_count
2066 }
2067
2068 pub fn trailing_excerpt_update_count(&self) -> usize {
2069 self.trailing_excerpt_update_count
2070 }
2071
2072 pub fn language(&self) -> Option<&Arc<Language>> {
2073 self.excerpts
2074 .iter()
2075 .next()
2076 .and_then(|excerpt| excerpt.buffer.language())
2077 }
2078
2079 pub fn is_dirty(&self) -> bool {
2080 self.is_dirty
2081 }
2082
2083 pub fn has_conflict(&self) -> bool {
2084 self.has_conflict
2085 }
2086
2087 pub fn diagnostic_group<'a, O>(
2088 &'a self,
2089 group_id: usize,
2090 ) -> impl Iterator<Item = DiagnosticEntry<O>> + 'a
2091 where
2092 O: text::FromAnchor + 'a,
2093 {
2094 self.as_singleton()
2095 .into_iter()
2096 .flat_map(move |excerpt| excerpt.buffer.diagnostic_group(group_id))
2097 }
2098
2099 pub fn diagnostics_in_range<'a, T, O>(
2100 &'a self,
2101 range: Range<T>,
2102 ) -> impl Iterator<Item = DiagnosticEntry<O>> + 'a
2103 where
2104 T: 'a + ToOffset,
2105 O: 'a + text::FromAnchor,
2106 {
2107 self.as_singleton().into_iter().flat_map(move |excerpt| {
2108 excerpt
2109 .buffer
2110 .diagnostics_in_range(range.start.to_offset(self)..range.end.to_offset(self))
2111 })
2112 }
2113
2114 pub fn range_for_syntax_ancestor<T: ToOffset>(&self, range: Range<T>) -> Option<Range<usize>> {
2115 let range = range.start.to_offset(self)..range.end.to_offset(self);
2116
2117 let mut cursor = self.excerpts.cursor::<usize>();
2118 cursor.seek(&range.start, Bias::Right, &());
2119 let start_excerpt = cursor.item();
2120
2121 cursor.seek(&range.end, Bias::Right, &());
2122 let end_excerpt = cursor.item();
2123
2124 start_excerpt
2125 .zip(end_excerpt)
2126 .and_then(|(start_excerpt, end_excerpt)| {
2127 if start_excerpt.id != end_excerpt.id {
2128 return None;
2129 }
2130
2131 let excerpt_buffer_start =
2132 start_excerpt.range.start.to_offset(&start_excerpt.buffer);
2133 let excerpt_buffer_end = excerpt_buffer_start + start_excerpt.text_summary.bytes;
2134
2135 let start_in_buffer =
2136 excerpt_buffer_start + range.start.saturating_sub(*cursor.start());
2137 let end_in_buffer =
2138 excerpt_buffer_start + range.end.saturating_sub(*cursor.start());
2139 let mut ancestor_buffer_range = start_excerpt
2140 .buffer
2141 .range_for_syntax_ancestor(start_in_buffer..end_in_buffer)?;
2142 ancestor_buffer_range.start =
2143 cmp::max(ancestor_buffer_range.start, excerpt_buffer_start);
2144 ancestor_buffer_range.end = cmp::min(ancestor_buffer_range.end, excerpt_buffer_end);
2145
2146 let start = cursor.start() + (ancestor_buffer_range.start - excerpt_buffer_start);
2147 let end = cursor.start() + (ancestor_buffer_range.end - excerpt_buffer_start);
2148 Some(start..end)
2149 })
2150 }
2151
2152 pub fn outline(&self, theme: Option<&SyntaxTheme>) -> Option<Outline<Anchor>> {
2153 let excerpt = self.as_singleton()?;
2154 let outline = excerpt.buffer.outline(theme)?;
2155 Some(Outline::new(
2156 outline
2157 .items
2158 .into_iter()
2159 .map(|item| OutlineItem {
2160 depth: item.depth,
2161 range: self.anchor_in_excerpt(excerpt.id.clone(), item.range.start)
2162 ..self.anchor_in_excerpt(excerpt.id.clone(), item.range.end),
2163 text: item.text,
2164 highlight_ranges: item.highlight_ranges,
2165 name_ranges: item.name_ranges,
2166 })
2167 .collect(),
2168 ))
2169 }
2170
2171 fn buffer_snapshot_for_excerpt<'a>(
2172 &'a self,
2173 excerpt_id: &'a ExcerptId,
2174 ) -> Option<(usize, &'a BufferSnapshot)> {
2175 let mut cursor = self.excerpts.cursor::<Option<&ExcerptId>>();
2176 cursor.seek(&Some(excerpt_id), Bias::Left, &());
2177 if let Some(excerpt) = cursor.item() {
2178 if excerpt.id == *excerpt_id {
2179 return Some((excerpt.buffer_id, &excerpt.buffer));
2180 }
2181 }
2182 None
2183 }
2184
2185 pub fn remote_selections_in_range<'a>(
2186 &'a self,
2187 range: &'a Range<Anchor>,
2188 ) -> impl 'a + Iterator<Item = (ReplicaId, Selection<Anchor>)> {
2189 let mut cursor = self.excerpts.cursor::<Option<&ExcerptId>>();
2190 cursor.seek(&Some(&range.start.excerpt_id), Bias::Left, &());
2191 cursor
2192 .take_while(move |excerpt| excerpt.id <= range.end.excerpt_id)
2193 .flat_map(move |excerpt| {
2194 let mut query_range = excerpt.range.start.clone()..excerpt.range.end.clone();
2195 if excerpt.id == range.start.excerpt_id {
2196 query_range.start = range.start.text_anchor.clone();
2197 }
2198 if excerpt.id == range.end.excerpt_id {
2199 query_range.end = range.end.text_anchor.clone();
2200 }
2201
2202 excerpt
2203 .buffer
2204 .remote_selections_in_range(query_range)
2205 .flat_map(move |(replica_id, selections)| {
2206 selections.map(move |selection| {
2207 let mut start = Anchor {
2208 buffer_id: excerpt.buffer_id,
2209 excerpt_id: excerpt.id.clone(),
2210 text_anchor: selection.start.clone(),
2211 };
2212 let mut end = Anchor {
2213 buffer_id: excerpt.buffer_id,
2214 excerpt_id: excerpt.id.clone(),
2215 text_anchor: selection.end.clone(),
2216 };
2217 if range.start.cmp(&start, self).unwrap().is_gt() {
2218 start = range.start.clone();
2219 }
2220 if range.end.cmp(&end, self).unwrap().is_lt() {
2221 end = range.end.clone();
2222 }
2223
2224 (
2225 replica_id,
2226 Selection {
2227 id: selection.id,
2228 start,
2229 end,
2230 reversed: selection.reversed,
2231 goal: selection.goal,
2232 },
2233 )
2234 })
2235 })
2236 })
2237 }
2238}
2239
2240impl History {
2241 fn start_transaction(&mut self, now: Instant) -> Option<TransactionId> {
2242 self.transaction_depth += 1;
2243 if self.transaction_depth == 1 {
2244 let id = self.next_transaction_id.tick();
2245 self.undo_stack.push(Transaction {
2246 id,
2247 buffer_transactions: Default::default(),
2248 first_edit_at: now,
2249 last_edit_at: now,
2250 suppress_grouping: false,
2251 });
2252 Some(id)
2253 } else {
2254 None
2255 }
2256 }
2257
2258 fn end_transaction(
2259 &mut self,
2260 now: Instant,
2261 buffer_transactions: HashMap<usize, TransactionId>,
2262 ) -> bool {
2263 assert_ne!(self.transaction_depth, 0);
2264 self.transaction_depth -= 1;
2265 if self.transaction_depth == 0 {
2266 if buffer_transactions.is_empty() {
2267 self.undo_stack.pop();
2268 false
2269 } else {
2270 let transaction = self.undo_stack.last_mut().unwrap();
2271 transaction.last_edit_at = now;
2272 for (buffer_id, transaction_id) in buffer_transactions {
2273 transaction
2274 .buffer_transactions
2275 .entry(buffer_id)
2276 .or_insert(transaction_id);
2277 }
2278 true
2279 }
2280 } else {
2281 false
2282 }
2283 }
2284
2285 fn push_transaction<'a, T>(&mut self, buffer_transactions: T, now: Instant)
2286 where
2287 T: IntoIterator<Item = (&'a ModelHandle<Buffer>, &'a language::Transaction)>,
2288 {
2289 assert_eq!(self.transaction_depth, 0);
2290 self.undo_stack.push(Transaction {
2291 id: self.next_transaction_id.tick(),
2292 buffer_transactions: buffer_transactions
2293 .into_iter()
2294 .map(|(buffer, transaction)| (buffer.id(), transaction.id))
2295 .collect(),
2296 first_edit_at: now,
2297 last_edit_at: now,
2298 suppress_grouping: false,
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 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 now += 2 * group_interval;
3678 multibuffer.start_transaction_at(now, cx);
3679 multibuffer.edit([2..2], "C", cx);
3680 multibuffer.end_transaction_at(now, cx);
3681 assert_eq!(multibuffer.read(cx).text(), "ABC1234\nAB5678");
3682
3683 multibuffer.undo(cx);
3684 assert_eq!(multibuffer.read(cx).text(), "AB1234\nAB5678");
3685
3686 multibuffer.undo(cx);
3687 assert_eq!(multibuffer.read(cx).text(), "1234\n5678");
3688
3689 multibuffer.redo(cx);
3690 assert_eq!(multibuffer.read(cx).text(), "AB1234\nAB5678");
3691
3692 multibuffer.redo(cx);
3693 assert_eq!(multibuffer.read(cx).text(), "ABC1234\nAB5678");
3694
3695 buffer_1.update(cx, |buffer_1, cx| buffer_1.undo(cx));
3696 assert_eq!(multibuffer.read(cx).text(), "AB1234\nAB5678");
3697
3698 multibuffer.undo(cx);
3699 assert_eq!(multibuffer.read(cx).text(), "1234\n5678");
3700
3701 multibuffer.redo(cx);
3702 assert_eq!(multibuffer.read(cx).text(), "AB1234\nAB5678");
3703
3704 multibuffer.redo(cx);
3705 assert_eq!(multibuffer.read(cx).text(), "ABC1234\nAB5678");
3706
3707 multibuffer.undo(cx);
3708 assert_eq!(multibuffer.read(cx).text(), "AB1234\nAB5678");
3709
3710 buffer_1.update(cx, |buffer_1, cx| buffer_1.redo(cx));
3711 assert_eq!(multibuffer.read(cx).text(), "ABC1234\nAB5678");
3712
3713 multibuffer.undo(cx);
3714 assert_eq!(multibuffer.read(cx).text(), "C1234\n5678");
3715 });
3716 }
3717}