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