1mod anchor;
2mod point;
3pub mod rope;
4mod selection;
5
6pub use anchor::*;
7pub use point::*;
8pub use rope::{ChunksIter, Rope, TextSummary};
9use seahash::SeaHasher;
10pub use selection::*;
11use similar::{ChangeTag, TextDiff};
12use tree_sitter::{InputEdit, Parser};
13
14use crate::{
15 editor::Bias,
16 language::{Language, Tree},
17 operation_queue::{self, OperationQueue},
18 sum_tree::{self, FilterCursor, SeekBias, SumTree},
19 time::{self, ReplicaId},
20 worktree::FileHandle,
21};
22use anyhow::{anyhow, Result};
23use gpui::{AppContext, Entity, ModelContext, Task};
24use lazy_static::lazy_static;
25use std::{
26 cell::RefCell,
27 cmp,
28 hash::BuildHasher,
29 iter::{self, Iterator},
30 mem,
31 ops::Range,
32 str,
33 sync::Arc,
34 time::{Duration, Instant, SystemTime, UNIX_EPOCH},
35};
36
37const UNDO_GROUP_INTERVAL: Duration = Duration::from_millis(300);
38
39#[derive(Clone, Default)]
40struct DeterministicState;
41
42impl BuildHasher for DeterministicState {
43 type Hasher = SeaHasher;
44
45 fn build_hasher(&self) -> Self::Hasher {
46 SeaHasher::new()
47 }
48}
49
50#[cfg(test)]
51type HashMap<K, V> = std::collections::HashMap<K, V, DeterministicState>;
52
53#[cfg(test)]
54type HashSet<T> = std::collections::HashSet<T, DeterministicState>;
55
56#[cfg(not(test))]
57type HashMap<K, V> = std::collections::HashMap<K, V>;
58
59#[cfg(not(test))]
60type HashSet<T> = std::collections::HashSet<T>;
61
62thread_local! {
63 pub static PARSER: RefCell<Parser> = RefCell::new(Parser::new());
64}
65
66pub struct Buffer {
67 fragments: SumTree<Fragment>,
68 visible_text: Rope,
69 deleted_text: Rope,
70 insertion_splits: HashMap<time::Local, SumTree<InsertionSplit>>,
71 pub version: time::Global,
72 saved_version: time::Global,
73 saved_mtime: SystemTime,
74 last_edit: time::Local,
75 undo_map: UndoMap,
76 history: History,
77 file: Option<FileHandle>,
78 language: Option<Arc<Language>>,
79 tree: Option<(Tree, time::Global)>,
80 is_parsing: bool,
81 selections: HashMap<SelectionSetId, Arc<[Selection]>>,
82 pub selections_last_update: SelectionsVersion,
83 deferred_ops: OperationQueue<Operation>,
84 deferred_replicas: HashSet<ReplicaId>,
85 replica_id: ReplicaId,
86 local_clock: time::Local,
87 lamport_clock: time::Lamport,
88}
89
90#[derive(Clone)]
91struct Transaction {
92 start: time::Global,
93 buffer_was_dirty: bool,
94 edits: Vec<time::Local>,
95 selections_before: Option<(SelectionSetId, Arc<[Selection]>)>,
96 selections_after: Option<(SelectionSetId, Arc<[Selection]>)>,
97 first_edit_at: Instant,
98 last_edit_at: Instant,
99}
100
101#[derive(Clone)]
102pub struct History {
103 // TODO: Turn this into a String or Rope, maybe.
104 pub base_text: Arc<str>,
105 ops: HashMap<time::Local, EditOperation>,
106 undo_stack: Vec<Transaction>,
107 redo_stack: Vec<Transaction>,
108 transaction_depth: usize,
109 group_interval: Duration,
110}
111
112impl History {
113 pub fn new(base_text: Arc<str>) -> Self {
114 Self {
115 base_text,
116 ops: Default::default(),
117 undo_stack: Vec::new(),
118 redo_stack: Vec::new(),
119 transaction_depth: 0,
120 group_interval: UNDO_GROUP_INTERVAL,
121 }
122 }
123
124 fn push(&mut self, op: EditOperation) {
125 self.ops.insert(op.id, op);
126 }
127
128 fn start_transaction(
129 &mut self,
130 start: time::Global,
131 buffer_was_dirty: bool,
132 selections: Option<(SelectionSetId, Arc<[Selection]>)>,
133 now: Instant,
134 ) {
135 self.transaction_depth += 1;
136 if self.transaction_depth == 1 {
137 self.undo_stack.push(Transaction {
138 start,
139 buffer_was_dirty,
140 edits: Vec::new(),
141 selections_before: selections,
142 selections_after: None,
143 first_edit_at: now,
144 last_edit_at: now,
145 });
146 }
147 }
148
149 fn end_transaction(
150 &mut self,
151 selections: Option<(SelectionSetId, Arc<[Selection]>)>,
152 now: Instant,
153 ) -> Option<&Transaction> {
154 assert_ne!(self.transaction_depth, 0);
155 self.transaction_depth -= 1;
156 if self.transaction_depth == 0 {
157 let transaction = self.undo_stack.last_mut().unwrap();
158 transaction.selections_after = selections;
159 transaction.last_edit_at = now;
160 Some(transaction)
161 } else {
162 None
163 }
164 }
165
166 fn group(&mut self) {
167 let mut new_len = self.undo_stack.len();
168 let mut transactions = self.undo_stack.iter_mut();
169
170 if let Some(mut transaction) = transactions.next_back() {
171 for prev_transaction in transactions.next_back() {
172 if transaction.first_edit_at - prev_transaction.last_edit_at <= self.group_interval
173 {
174 prev_transaction.edits.append(&mut transaction.edits);
175 prev_transaction.last_edit_at = transaction.last_edit_at;
176 prev_transaction.selections_after = transaction.selections_after.take();
177 transaction = prev_transaction;
178 new_len -= 1;
179 } else {
180 break;
181 }
182 }
183 }
184
185 self.undo_stack.truncate(new_len);
186 }
187
188 fn push_undo(&mut self, edit_id: time::Local) {
189 assert_ne!(self.transaction_depth, 0);
190 self.undo_stack.last_mut().unwrap().edits.push(edit_id);
191 }
192
193 fn pop_undo(&mut self) -> Option<&Transaction> {
194 assert_eq!(self.transaction_depth, 0);
195 if let Some(transaction) = self.undo_stack.pop() {
196 self.redo_stack.push(transaction);
197 self.redo_stack.last()
198 } else {
199 None
200 }
201 }
202
203 fn pop_redo(&mut self) -> Option<&Transaction> {
204 assert_eq!(self.transaction_depth, 0);
205 if let Some(transaction) = self.redo_stack.pop() {
206 self.undo_stack.push(transaction);
207 self.undo_stack.last()
208 } else {
209 None
210 }
211 }
212}
213
214#[derive(Clone, Default, Debug)]
215struct UndoMap(HashMap<time::Local, Vec<UndoOperation>>);
216
217impl UndoMap {
218 fn insert(&mut self, undo: UndoOperation) {
219 self.0.entry(undo.edit_id).or_default().push(undo);
220 }
221
222 fn is_undone(&self, edit_id: time::Local) -> bool {
223 self.undo_count(edit_id) % 2 == 1
224 }
225
226 fn was_undone(&self, edit_id: time::Local, version: &time::Global) -> bool {
227 let undo_count = self
228 .0
229 .get(&edit_id)
230 .unwrap_or(&Vec::new())
231 .iter()
232 .filter(|undo| version.observed(undo.id))
233 .map(|undo| undo.count)
234 .max()
235 .unwrap_or(0);
236 undo_count % 2 == 1
237 }
238
239 fn undo_count(&self, edit_id: time::Local) -> u32 {
240 self.0
241 .get(&edit_id)
242 .unwrap_or(&Vec::new())
243 .iter()
244 .map(|undo| undo.count)
245 .max()
246 .unwrap_or(0)
247 }
248}
249
250struct Edits<'a, F: Fn(&FragmentSummary) -> bool> {
251 deleted_text: &'a Rope,
252 cursor: FilterCursor<'a, F, Fragment, FragmentTextSummary>,
253 undos: &'a UndoMap,
254 since: time::Global,
255 delta: isize,
256}
257
258#[derive(Clone, Debug, Default, Eq, PartialEq)]
259pub struct Edit {
260 pub old_range: Range<usize>,
261 pub new_range: Range<usize>,
262 pub old_lines: Point,
263}
264
265impl Edit {
266 pub fn delta(&self) -> isize {
267 (self.new_range.end - self.new_range.start) as isize
268 - (self.old_range.end - self.old_range.start) as isize
269 }
270
271 pub fn old_extent(&self) -> usize {
272 self.old_range.end - self.old_range.start
273 }
274}
275
276struct Diff {
277 base_version: time::Global,
278 new_text: Arc<str>,
279 changes: Vec<(ChangeTag, usize)>,
280}
281
282#[derive(Clone, Eq, PartialEq, Debug)]
283pub struct Insertion {
284 id: time::Local,
285 parent_id: time::Local,
286 offset_in_parent: usize,
287 lamport_timestamp: time::Lamport,
288}
289
290#[derive(Eq, PartialEq, Clone, Debug)]
291struct Fragment {
292 id: FragmentId,
293 insertion: Arc<Insertion>,
294 range_in_insertion: Range<usize>,
295 deletions: HashSet<time::Local>,
296 max_undos: time::Global,
297 visible: bool,
298}
299
300#[derive(Eq, PartialEq, Clone, Debug)]
301pub struct FragmentSummary {
302 text: FragmentTextSummary,
303 max_fragment_id: FragmentId,
304 max_version: time::Global,
305}
306
307#[derive(Default, Clone, Debug, PartialEq, Eq)]
308struct FragmentTextSummary {
309 visible: usize,
310 deleted: usize,
311}
312
313impl<'a> sum_tree::Dimension<'a, FragmentSummary> for FragmentTextSummary {
314 fn add_summary(&mut self, summary: &'a FragmentSummary) {
315 self.visible += summary.text.visible;
316 self.deleted += summary.text.deleted;
317 }
318}
319
320#[derive(Eq, PartialEq, Clone, Debug)]
321struct InsertionSplit {
322 extent: usize,
323 fragment_id: FragmentId,
324}
325
326#[derive(Eq, PartialEq, Clone, Debug)]
327struct InsertionSplitSummary {
328 extent: usize,
329}
330
331#[derive(Clone, Debug, Eq, PartialEq)]
332pub enum Operation {
333 Edit {
334 edit: EditOperation,
335 lamport_timestamp: time::Lamport,
336 },
337 Undo {
338 undo: UndoOperation,
339 lamport_timestamp: time::Lamport,
340 },
341 UpdateSelections {
342 set_id: SelectionSetId,
343 selections: Option<Arc<[Selection]>>,
344 lamport_timestamp: time::Lamport,
345 },
346}
347
348#[derive(Clone, Debug, Eq, PartialEq)]
349pub struct EditOperation {
350 id: time::Local,
351 start_id: time::Local,
352 start_offset: usize,
353 end_id: time::Local,
354 end_offset: usize,
355 version_in_range: time::Global,
356 new_text: Option<String>,
357}
358
359#[derive(Copy, Clone, Debug, Eq, PartialEq)]
360pub struct UndoOperation {
361 id: time::Local,
362 edit_id: time::Local,
363 count: u32,
364}
365
366impl Buffer {
367 pub fn new<T: Into<Arc<str>>>(
368 replica_id: ReplicaId,
369 base_text: T,
370 ctx: &mut ModelContext<Self>,
371 ) -> Self {
372 Self::build(replica_id, History::new(base_text.into()), None, None, ctx)
373 }
374
375 pub fn from_history(
376 replica_id: ReplicaId,
377 history: History,
378 file: Option<FileHandle>,
379 language: Option<Arc<Language>>,
380 ctx: &mut ModelContext<Self>,
381 ) -> Self {
382 Self::build(replica_id, history, file, language, ctx)
383 }
384
385 fn build(
386 replica_id: ReplicaId,
387 history: History,
388 file: Option<FileHandle>,
389 language: Option<Arc<Language>>,
390 ctx: &mut ModelContext<Self>,
391 ) -> Self {
392 let saved_mtime;
393 if let Some(file) = file.as_ref() {
394 saved_mtime = file.mtime();
395 file.observe_from_model(ctx, |this, file, ctx| {
396 let version = this.version.clone();
397 if this.version == this.saved_version {
398 if file.is_deleted() {
399 ctx.emit(Event::Dirtied);
400 } else {
401 ctx.spawn(|handle, mut ctx| async move {
402 let (current_version, history) = handle.read_with(&ctx, |this, ctx| {
403 (this.version.clone(), file.load_history(ctx.as_ref()))
404 });
405 if let (Ok(history), true) = (history.await, current_version == version)
406 {
407 let diff = handle
408 .read_with(&ctx, |this, ctx| this.diff(history.base_text, ctx))
409 .await;
410 handle.update(&mut ctx, |this, ctx| {
411 if let Some(_ops) = this.set_text_via_diff(diff, ctx) {
412 this.saved_version = this.version.clone();
413 this.saved_mtime = file.mtime();
414 ctx.emit(Event::Reloaded);
415 }
416 });
417 }
418 })
419 .detach();
420 }
421 }
422 ctx.emit(Event::FileHandleChanged);
423 });
424 } else {
425 saved_mtime = UNIX_EPOCH;
426 }
427
428 let mut visible_text = Rope::new();
429 let mut insertion_splits = HashMap::default();
430 let mut fragments = SumTree::new();
431
432 let base_text = Rope::from(history.base_text.as_ref());
433 let base_insertion = Arc::new(Insertion {
434 id: time::Local::default(),
435 parent_id: time::Local::default(),
436 offset_in_parent: 0,
437 lamport_timestamp: time::Lamport::default(),
438 });
439
440 insertion_splits.insert(
441 base_insertion.id,
442 SumTree::from_item(
443 InsertionSplit {
444 fragment_id: FragmentId::min_value().clone(),
445 extent: 0,
446 },
447 &(),
448 ),
449 );
450 fragments.push(
451 Fragment::new(
452 FragmentId::min_value().clone(),
453 base_insertion.clone(),
454 0..0,
455 ),
456 &(),
457 );
458
459 if base_text.len() > 0 {
460 let base_fragment_id =
461 FragmentId::between(&FragmentId::min_value(), &FragmentId::max_value());
462 let range_in_insertion = 0..base_text.len();
463
464 visible_text = base_text.clone();
465 insertion_splits.get_mut(&base_insertion.id).unwrap().push(
466 InsertionSplit {
467 fragment_id: base_fragment_id.clone(),
468 extent: range_in_insertion.end,
469 },
470 &(),
471 );
472 fragments.push(
473 Fragment::new(base_fragment_id, base_insertion, range_in_insertion.clone()),
474 &(),
475 );
476 }
477
478 let mut result = Self {
479 visible_text,
480 deleted_text: Rope::new(),
481 fragments,
482 insertion_splits,
483 version: time::Global::new(),
484 saved_version: time::Global::new(),
485 last_edit: time::Local::default(),
486 undo_map: Default::default(),
487 history,
488 file,
489 tree: None,
490 is_parsing: false,
491 language,
492 saved_mtime,
493 selections: HashMap::default(),
494 selections_last_update: 0,
495 deferred_ops: OperationQueue::new(),
496 deferred_replicas: HashSet::default(),
497 replica_id,
498 local_clock: time::Local::new(replica_id),
499 lamport_clock: time::Lamport::new(replica_id),
500 };
501 result.reparse(ctx);
502 result
503 }
504
505 pub fn snapshot(&self) -> Rope {
506 self.visible_text.clone()
507 }
508
509 pub fn file(&self) -> Option<&FileHandle> {
510 self.file.as_ref()
511 }
512
513 pub fn save(
514 &mut self,
515 new_file: Option<FileHandle>,
516 ctx: &mut ModelContext<Self>,
517 ) -> Task<Result<()>> {
518 let snapshot = self.snapshot();
519 let version = self.version.clone();
520 let file = self.file.clone();
521
522 ctx.spawn(|handle, mut ctx| async move {
523 if let Some(file) = new_file.as_ref().or(file.as_ref()) {
524 let result = ctx.read(|ctx| file.save(snapshot, ctx.as_ref())).await;
525 if result.is_ok() {
526 handle.update(&mut ctx, |me, ctx| me.did_save(version, new_file, ctx));
527 }
528 result
529 } else {
530 Ok(())
531 }
532 })
533 }
534
535 fn did_save(
536 &mut self,
537 version: time::Global,
538 file: Option<FileHandle>,
539 ctx: &mut ModelContext<Buffer>,
540 ) {
541 if file.is_some() {
542 self.file = file;
543 }
544 if let Some(file) = &self.file {
545 self.saved_mtime = file.mtime();
546 }
547 self.saved_version = version;
548 ctx.emit(Event::Saved);
549 }
550
551 fn should_reparse(&self) -> bool {
552 self.tree
553 .as_ref()
554 .map_or(true, |(_, tree_version)| *tree_version != self.version)
555 }
556
557 fn reparse(&mut self, ctx: &mut ModelContext<Self>) {
558 // Avoid spawning a new parsing task if the buffer is already being reparsed
559 // due to an earlier edit.
560 if self.is_parsing {
561 return;
562 }
563
564 if let Some(language) = self.language.clone() {
565 self.is_parsing = true;
566 ctx.spawn(|handle, mut ctx| async move {
567 while handle.read_with(&ctx, |this, _| this.should_reparse()) {
568 // The parse tree is out of date, so we clone it and synchronously splice in all
569 // the edits that have happened since the last parse.
570 let (new_version, new_text) = handle
571 .read_with(&ctx, |this, _| (this.version(), this.visible_text.clone()));
572 let mut new_tree = None;
573 handle.update(&mut ctx, |this, _| {
574 if let Some((mut tree, tree_version)) = this.tree.clone() {
575 let mut delta = 0_isize;
576 for Edit {
577 old_range,
578 new_range,
579 old_lines,
580 } in this.edits_since(tree_version)
581 {
582 let start_offset = (old_range.start as isize + delta) as usize;
583 let start_point = new_text.to_point(start_offset);
584 let old_bytes = old_range.end - old_range.start;
585 let new_bytes = new_range.end - new_range.start;
586 tree.edit(&InputEdit {
587 start_byte: start_offset,
588 old_end_byte: start_offset + old_bytes,
589 new_end_byte: start_offset + new_bytes,
590 start_position: start_point.into(),
591 old_end_position: (start_point + old_lines).into(),
592 new_end_position: new_text
593 .to_point(start_offset + new_bytes)
594 .into(),
595 });
596 delta += new_bytes as isize - old_bytes as isize;
597 }
598
599 new_tree = Some(tree);
600 }
601 });
602
603 // Parse the current text in a background thread.
604 let new_tree = ctx
605 .background_executor()
606 .spawn({
607 let language = language.clone();
608 async move { Self::parse_text(&new_text, new_tree, &language) }
609 })
610 .await;
611
612 handle.update(&mut ctx, |this, ctx| {
613 this.tree = Some((new_tree, new_version));
614 ctx.emit(Event::Reparsed);
615 });
616 }
617 handle.update(&mut ctx, |this, _| this.is_parsing = false);
618 })
619 .detach();
620 }
621 }
622
623 fn parse_text(text: &Rope, old_tree: Option<Tree>, language: &Language) -> Tree {
624 PARSER.with(|parser| {
625 let mut parser = parser.borrow_mut();
626 parser
627 .set_language(language.grammar)
628 .expect("incompatible grammar");
629 let mut chunks = text.chunks_in_range(0..text.len());
630 let tree = parser
631 .parse_with(
632 &mut move |offset, _| {
633 chunks.seek(offset);
634 chunks.next().unwrap_or("").as_bytes()
635 },
636 old_tree.as_ref(),
637 )
638 .unwrap();
639 tree
640 })
641 }
642
643 fn diff(&self, new_text: Arc<str>, ctx: &AppContext) -> Task<Diff> {
644 // TODO: it would be nice to not allocate here.
645 let old_text = self.text();
646 let base_version = self.version();
647 ctx.background_executor().spawn(async move {
648 let changes = TextDiff::from_lines(old_text.as_str(), new_text.as_ref())
649 .iter_all_changes()
650 .map(|c| (c.tag(), c.value().len()))
651 .collect::<Vec<_>>();
652 Diff {
653 base_version,
654 new_text,
655 changes,
656 }
657 })
658 }
659
660 fn set_text_via_diff(
661 &mut self,
662 diff: Diff,
663 ctx: &mut ModelContext<Self>,
664 ) -> Option<Vec<Operation>> {
665 if self.version == diff.base_version {
666 self.start_transaction(None).unwrap();
667 let mut operations = Vec::new();
668 let mut offset = 0;
669 for (tag, len) in diff.changes {
670 let range = offset..(offset + len);
671 match tag {
672 ChangeTag::Equal => offset += len,
673 ChangeTag::Delete => operations
674 .extend_from_slice(&self.edit(Some(range), "", Some(ctx)).unwrap()),
675 ChangeTag::Insert => {
676 operations.extend_from_slice(
677 &self
678 .edit(Some(offset..offset), &diff.new_text[range], Some(ctx))
679 .unwrap(),
680 );
681 offset += len;
682 }
683 }
684 }
685 self.end_transaction(None, Some(ctx)).unwrap();
686 Some(operations)
687 } else {
688 None
689 }
690 }
691
692 pub fn is_dirty(&self) -> bool {
693 self.version > self.saved_version || self.file.as_ref().map_or(false, |f| f.is_deleted())
694 }
695
696 pub fn has_conflict(&self) -> bool {
697 self.version > self.saved_version
698 && self
699 .file
700 .as_ref()
701 .map_or(false, |f| f.mtime() > self.saved_mtime)
702 }
703
704 pub fn version(&self) -> time::Global {
705 self.version.clone()
706 }
707
708 pub fn text_summary(&self) -> TextSummary {
709 self.visible_text.summary()
710 }
711
712 pub fn text_summary_for_range(&self, range: Range<usize>) -> TextSummary {
713 self.visible_text.cursor(range.start).summary(range.end)
714 }
715
716 pub fn len(&self) -> usize {
717 self.fragments.extent::<usize>()
718 }
719
720 pub fn line_len(&self, row: u32) -> u32 {
721 let row_start_offset = Point::new(row, 0).to_offset(self);
722 let row_end_offset = if row >= self.max_point().row {
723 self.len()
724 } else {
725 Point::new(row + 1, 0).to_offset(self) - 1
726 };
727 (row_end_offset - row_start_offset) as u32
728 }
729
730 pub fn max_point(&self) -> Point {
731 self.visible_text.max_point()
732 }
733
734 pub fn line(&self, row: u32) -> String {
735 self.chars_at(Point::new(row, 0))
736 .take_while(|c| *c != '\n')
737 .collect()
738 }
739
740 pub fn text(&self) -> String {
741 self.text_for_range(0..self.len()).collect()
742 }
743
744 pub fn text_for_range<'a, T: ToOffset>(&'a self, range: Range<T>) -> ChunksIter<'a> {
745 let start = range.start.to_offset(self);
746 let end = range.end.to_offset(self);
747 self.visible_text.chunks_in_range(start..end)
748 }
749
750 pub fn chars(&self) -> impl Iterator<Item = char> + '_ {
751 self.chars_at(0)
752 }
753
754 pub fn chars_at<T: ToOffset>(&self, position: T) -> impl Iterator<Item = char> + '_ {
755 let offset = position.to_offset(self);
756 self.visible_text.chars_at(offset)
757 }
758
759 pub fn selections_changed_since(&self, since: SelectionsVersion) -> bool {
760 self.selections_last_update != since
761 }
762
763 pub fn edits_since<'a>(&'a self, since: time::Global) -> impl 'a + Iterator<Item = Edit> {
764 let since_2 = since.clone();
765 let cursor = self
766 .fragments
767 .filter(move |summary| summary.max_version.changed_since(&since_2));
768
769 Edits {
770 deleted_text: &self.deleted_text,
771 cursor,
772 undos: &self.undo_map,
773 since,
774 delta: 0,
775 }
776 }
777
778 pub fn deferred_ops_len(&self) -> usize {
779 self.deferred_ops.len()
780 }
781
782 pub fn start_transaction(&mut self, set_id: Option<SelectionSetId>) -> Result<()> {
783 self.start_transaction_at(set_id, Instant::now())
784 }
785
786 fn start_transaction_at(&mut self, set_id: Option<SelectionSetId>, now: Instant) -> Result<()> {
787 let selections = if let Some(set_id) = set_id {
788 let selections = self
789 .selections
790 .get(&set_id)
791 .ok_or_else(|| anyhow!("invalid selection set {:?}", set_id))?;
792 Some((set_id, selections.clone()))
793 } else {
794 None
795 };
796 self.history
797 .start_transaction(self.version.clone(), self.is_dirty(), selections, now);
798 Ok(())
799 }
800
801 pub fn end_transaction(
802 &mut self,
803 set_id: Option<SelectionSetId>,
804 ctx: Option<&mut ModelContext<Self>>,
805 ) -> Result<()> {
806 self.end_transaction_at(set_id, Instant::now(), ctx)
807 }
808
809 fn end_transaction_at(
810 &mut self,
811 set_id: Option<SelectionSetId>,
812 now: Instant,
813 ctx: Option<&mut ModelContext<Self>>,
814 ) -> Result<()> {
815 let selections = if let Some(set_id) = set_id {
816 let selections = self
817 .selections
818 .get(&set_id)
819 .ok_or_else(|| anyhow!("invalid selection set {:?}", set_id))?;
820 Some((set_id, selections.clone()))
821 } else {
822 None
823 };
824
825 if let Some(transaction) = self.history.end_transaction(selections, now) {
826 let since = transaction.start.clone();
827 let was_dirty = transaction.buffer_was_dirty;
828 self.history.group();
829
830 if let Some(ctx) = ctx {
831 ctx.notify();
832
833 if self.edits_since(since).next().is_some() {
834 self.did_edit(was_dirty, ctx);
835 self.reparse(ctx);
836 }
837 }
838 }
839
840 Ok(())
841 }
842
843 pub fn edit<I, S, T>(
844 &mut self,
845 old_ranges: I,
846 new_text: T,
847 ctx: Option<&mut ModelContext<Self>>,
848 ) -> Result<Vec<Operation>>
849 where
850 I: IntoIterator<Item = Range<S>>,
851 S: ToOffset,
852 T: Into<String>,
853 {
854 self.start_transaction_at(None, Instant::now())?;
855
856 let new_text = new_text.into();
857 let old_ranges = old_ranges
858 .into_iter()
859 .map(|range| range.start.to_offset(self)..range.end.to_offset(self))
860 .collect::<Vec<Range<usize>>>();
861
862 let new_text = if new_text.len() > 0 {
863 Some(new_text)
864 } else {
865 None
866 };
867
868 let has_new_text = new_text.is_some();
869 let ops = self.splice_fragments(
870 old_ranges
871 .into_iter()
872 .filter(|old_range| has_new_text || old_range.end > old_range.start),
873 new_text.into(),
874 );
875
876 for op in &ops {
877 if let Operation::Edit { edit, .. } = op {
878 self.history.push(edit.clone());
879 self.history.push_undo(edit.id);
880 }
881 }
882
883 if let Some(op) = ops.last() {
884 if let Operation::Edit { edit, .. } = op {
885 self.last_edit = edit.id;
886 self.version.observe(edit.id);
887 } else {
888 unreachable!()
889 }
890 }
891
892 self.end_transaction_at(None, Instant::now(), ctx)?;
893
894 Ok(ops)
895 }
896
897 fn did_edit(&self, was_dirty: bool, ctx: &mut ModelContext<Self>) {
898 ctx.emit(Event::Edited);
899 if !was_dirty {
900 ctx.emit(Event::Dirtied);
901 }
902 }
903
904 pub fn add_selection_set(
905 &mut self,
906 selections: impl Into<Arc<[Selection]>>,
907 ctx: Option<&mut ModelContext<Self>>,
908 ) -> (SelectionSetId, Operation) {
909 let selections = selections.into();
910 let lamport_timestamp = self.lamport_clock.tick();
911 self.selections
912 .insert(lamport_timestamp, Arc::clone(&selections));
913 self.selections_last_update += 1;
914
915 if let Some(ctx) = ctx {
916 ctx.notify();
917 }
918
919 (
920 lamport_timestamp,
921 Operation::UpdateSelections {
922 set_id: lamport_timestamp,
923 selections: Some(selections),
924 lamport_timestamp,
925 },
926 )
927 }
928
929 pub fn update_selection_set(
930 &mut self,
931 set_id: SelectionSetId,
932 selections: impl Into<Arc<[Selection]>>,
933 ctx: Option<&mut ModelContext<Self>>,
934 ) -> Result<Operation> {
935 let selections = selections.into();
936 self.selections.insert(set_id, selections.clone());
937
938 let lamport_timestamp = self.lamport_clock.tick();
939 self.selections_last_update += 1;
940
941 if let Some(ctx) = ctx {
942 ctx.notify();
943 }
944
945 Ok(Operation::UpdateSelections {
946 set_id,
947 selections: Some(selections),
948 lamport_timestamp,
949 })
950 }
951
952 pub fn remove_selection_set(
953 &mut self,
954 set_id: SelectionSetId,
955 ctx: Option<&mut ModelContext<Self>>,
956 ) -> Result<Operation> {
957 self.selections
958 .remove(&set_id)
959 .ok_or_else(|| anyhow!("invalid selection set id {:?}", set_id))?;
960 let lamport_timestamp = self.lamport_clock.tick();
961 self.selections_last_update += 1;
962
963 if let Some(ctx) = ctx {
964 ctx.notify();
965 }
966
967 Ok(Operation::UpdateSelections {
968 set_id,
969 selections: None,
970 lamport_timestamp,
971 })
972 }
973
974 pub fn selections(&self, set_id: SelectionSetId) -> Result<&[Selection]> {
975 self.selections
976 .get(&set_id)
977 .map(|s| s.as_ref())
978 .ok_or_else(|| anyhow!("invalid selection set id {:?}", set_id))
979 }
980
981 pub fn apply_ops<I: IntoIterator<Item = Operation>>(
982 &mut self,
983 ops: I,
984 ctx: Option<&mut ModelContext<Self>>,
985 ) -> Result<()> {
986 let was_dirty = self.is_dirty();
987 let old_version = self.version.clone();
988
989 let mut deferred_ops = Vec::new();
990 for op in ops {
991 if self.can_apply_op(&op) {
992 self.apply_op(op)?;
993 } else {
994 self.deferred_replicas.insert(op.replica_id());
995 deferred_ops.push(op);
996 }
997 }
998 self.deferred_ops.insert(deferred_ops);
999 self.flush_deferred_ops()?;
1000
1001 if let Some(ctx) = ctx {
1002 ctx.notify();
1003 if self.edits_since(old_version).next().is_some() {
1004 self.did_edit(was_dirty, ctx);
1005 self.reparse(ctx);
1006 }
1007 }
1008
1009 Ok(())
1010 }
1011
1012 fn apply_op(&mut self, op: Operation) -> Result<()> {
1013 match op {
1014 Operation::Edit {
1015 edit,
1016 lamport_timestamp,
1017 ..
1018 } => {
1019 if !self.version.observed(edit.id) {
1020 self.apply_edit(
1021 edit.start_id,
1022 edit.start_offset,
1023 edit.end_id,
1024 edit.end_offset,
1025 edit.new_text.as_deref(),
1026 &edit.version_in_range,
1027 edit.id,
1028 lamport_timestamp,
1029 )?;
1030 self.version.observe(edit.id);
1031 self.history.push(edit);
1032 }
1033 }
1034 Operation::Undo {
1035 undo,
1036 lamport_timestamp,
1037 } => {
1038 if !self.version.observed(undo.id) {
1039 self.apply_undo(undo)?;
1040 self.version.observe(undo.id);
1041 self.lamport_clock.observe(lamport_timestamp);
1042 }
1043 }
1044 Operation::UpdateSelections {
1045 set_id,
1046 selections,
1047 lamport_timestamp,
1048 } => {
1049 if let Some(selections) = selections {
1050 self.selections.insert(set_id, selections);
1051 } else {
1052 self.selections.remove(&set_id);
1053 }
1054 self.lamport_clock.observe(lamport_timestamp);
1055 self.selections_last_update += 1;
1056 }
1057 }
1058 Ok(())
1059 }
1060
1061 fn apply_edit(
1062 &mut self,
1063 start_id: time::Local,
1064 start_offset: usize,
1065 end_id: time::Local,
1066 end_offset: usize,
1067 mut new_text: Option<&str>,
1068 version_in_range: &time::Global,
1069 local_timestamp: time::Local,
1070 lamport_timestamp: time::Lamport,
1071 ) -> Result<()> {
1072 let start_fragment_id = self.resolve_fragment_id(start_id, start_offset)?;
1073 let end_fragment_id = self.resolve_fragment_id(end_id, end_offset)?;
1074
1075 let mut old_visible_text = Rope::new();
1076 let mut old_deleted_text = Rope::new();
1077 let mut old_fragments = SumTree::new();
1078 mem::swap(&mut old_visible_text, &mut self.visible_text);
1079 mem::swap(&mut old_deleted_text, &mut self.deleted_text);
1080 mem::swap(&mut old_fragments, &mut self.fragments);
1081
1082 let mut fragments_cursor = old_fragments.cursor::<FragmentIdRef, FragmentTextSummary>();
1083
1084 let mut new_fragments =
1085 fragments_cursor.slice(&FragmentIdRef::new(&start_fragment_id), SeekBias::Left, &());
1086 let mut new_ropes =
1087 RopeBuilder::new(old_visible_text.cursor(0), old_deleted_text.cursor(0));
1088 new_ropes.push_tree(new_fragments.summary().text);
1089
1090 let start_fragment = fragments_cursor.item().unwrap();
1091 if start_offset == start_fragment.range_in_insertion.end {
1092 let fragment = fragments_cursor.item().unwrap().clone();
1093 new_ropes.push_fragment(&fragment, fragment.visible);
1094 new_fragments.push(fragment, &());
1095 fragments_cursor.next();
1096 }
1097
1098 while let Some(fragment) = fragments_cursor.item() {
1099 if new_text.is_none() && fragment.id > end_fragment_id {
1100 break;
1101 }
1102
1103 let mut fragment = fragment.clone();
1104
1105 if fragment.id == start_fragment_id || fragment.id == end_fragment_id {
1106 let split_start = if start_fragment_id == fragment.id {
1107 start_offset
1108 } else {
1109 fragment.range_in_insertion.start
1110 };
1111 let split_end = if end_fragment_id == fragment.id {
1112 end_offset
1113 } else {
1114 fragment.range_in_insertion.end
1115 };
1116 let (before_range, within_range, after_range) = self.split_fragment(
1117 fragments_cursor.prev_item().as_ref().unwrap(),
1118 &fragment,
1119 split_start..split_end,
1120 );
1121 let insertion = if let Some(new_text) = new_text {
1122 let prev_fragment = fragments_cursor.prev_item();
1123 Some(self.build_fragment_to_insert(
1124 before_range.as_ref().or(prev_fragment).unwrap(),
1125 within_range.as_ref().or(after_range.as_ref()),
1126 new_text,
1127 local_timestamp,
1128 lamport_timestamp,
1129 ))
1130 } else {
1131 None
1132 };
1133 if let Some(fragment) = before_range {
1134 new_ropes.push_fragment(&fragment, fragment.visible);
1135 new_fragments.push(fragment, &());
1136 }
1137 if let Some(fragment) = insertion {
1138 new_ropes.push_str(new_text.take().unwrap());
1139 new_fragments.push(fragment, &());
1140 }
1141 if let Some(mut fragment) = within_range {
1142 let fragment_was_visible = fragment.visible;
1143 if fragment.was_visible(&version_in_range, &self.undo_map) {
1144 fragment.deletions.insert(local_timestamp);
1145 if fragment.visible {
1146 fragment.visible = false;
1147 }
1148 }
1149
1150 new_ropes.push_fragment(&fragment, fragment_was_visible);
1151 new_fragments.push(fragment, &());
1152 }
1153 if let Some(fragment) = after_range {
1154 new_ropes.push_fragment(&fragment, fragment.visible);
1155 new_fragments.push(fragment, &());
1156 }
1157 } else {
1158 if new_text.is_some() && lamport_timestamp > fragment.insertion.lamport_timestamp {
1159 let new_text = new_text.take().unwrap();
1160 let fragment = self.build_fragment_to_insert(
1161 fragments_cursor.prev_item().as_ref().unwrap(),
1162 Some(&fragment),
1163 new_text,
1164 local_timestamp,
1165 lamport_timestamp,
1166 );
1167 new_ropes.push_str(new_text);
1168 new_fragments.push(fragment, &());
1169 }
1170
1171 let fragment_was_visible = fragment.visible;
1172 if fragment.id < end_fragment_id
1173 && fragment.was_visible(&version_in_range, &self.undo_map)
1174 {
1175 fragment.deletions.insert(local_timestamp);
1176 if fragment.visible {
1177 fragment.visible = false;
1178 }
1179 }
1180
1181 new_ropes.push_fragment(&fragment, fragment_was_visible);
1182 new_fragments.push(fragment, &());
1183 }
1184
1185 fragments_cursor.next();
1186 }
1187
1188 if let Some(new_text) = new_text {
1189 let fragment = self.build_fragment_to_insert(
1190 fragments_cursor.prev_item().as_ref().unwrap(),
1191 None,
1192 new_text,
1193 local_timestamp,
1194 lamport_timestamp,
1195 );
1196 new_ropes.push_str(new_text);
1197 new_fragments.push(fragment, &());
1198 }
1199
1200 let (visible_text, deleted_text) = new_ropes.finish();
1201 new_fragments.push_tree(fragments_cursor.suffix(&()), &());
1202
1203 self.fragments = new_fragments;
1204 self.visible_text = visible_text;
1205 self.deleted_text = deleted_text;
1206 self.local_clock.observe(local_timestamp);
1207 self.lamport_clock.observe(lamport_timestamp);
1208 Ok(())
1209 }
1210
1211 pub fn undo(&mut self, mut ctx: Option<&mut ModelContext<Self>>) -> Vec<Operation> {
1212 let was_dirty = self.is_dirty();
1213 let old_version = self.version.clone();
1214
1215 let mut ops = Vec::new();
1216 if let Some(transaction) = self.history.pop_undo() {
1217 let selections = transaction.selections_before.clone();
1218 for edit_id in transaction.edits.clone() {
1219 ops.push(self.undo_or_redo(edit_id).unwrap());
1220 }
1221
1222 if let Some((set_id, selections)) = selections {
1223 let _ = self.update_selection_set(set_id, selections, ctx.as_deref_mut());
1224 }
1225 }
1226
1227 if let Some(ctx) = ctx {
1228 ctx.notify();
1229 if self.edits_since(old_version).next().is_some() {
1230 self.did_edit(was_dirty, ctx);
1231 self.reparse(ctx);
1232 }
1233 }
1234
1235 ops
1236 }
1237
1238 pub fn redo(&mut self, mut ctx: Option<&mut ModelContext<Self>>) -> Vec<Operation> {
1239 let was_dirty = self.is_dirty();
1240 let old_version = self.version.clone();
1241
1242 let mut ops = Vec::new();
1243 if let Some(transaction) = self.history.pop_redo() {
1244 let selections = transaction.selections_after.clone();
1245 for edit_id in transaction.edits.clone() {
1246 ops.push(self.undo_or_redo(edit_id).unwrap());
1247 }
1248
1249 if let Some((set_id, selections)) = selections {
1250 let _ = self.update_selection_set(set_id, selections, ctx.as_deref_mut());
1251 }
1252 }
1253
1254 if let Some(ctx) = ctx {
1255 ctx.notify();
1256 if self.edits_since(old_version).next().is_some() {
1257 self.did_edit(was_dirty, ctx);
1258 self.reparse(ctx);
1259 }
1260 }
1261
1262 ops
1263 }
1264
1265 fn undo_or_redo(&mut self, edit_id: time::Local) -> Result<Operation> {
1266 let undo = UndoOperation {
1267 id: self.local_clock.tick(),
1268 edit_id,
1269 count: self.undo_map.undo_count(edit_id) + 1,
1270 };
1271 self.apply_undo(undo)?;
1272 self.version.observe(undo.id);
1273
1274 Ok(Operation::Undo {
1275 undo,
1276 lamport_timestamp: self.lamport_clock.tick(),
1277 })
1278 }
1279
1280 fn apply_undo(&mut self, undo: UndoOperation) -> Result<()> {
1281 let mut new_fragments;
1282 let mut old_visible_text = Rope::new();
1283 let mut old_deleted_text = Rope::new();
1284 mem::swap(&mut old_visible_text, &mut self.visible_text);
1285 mem::swap(&mut old_deleted_text, &mut self.deleted_text);
1286 let mut new_ropes =
1287 RopeBuilder::new(old_visible_text.cursor(0), old_deleted_text.cursor(0));
1288
1289 self.undo_map.insert(undo);
1290 let edit = &self.history.ops[&undo.edit_id];
1291 let start_fragment_id = self.resolve_fragment_id(edit.start_id, edit.start_offset)?;
1292 let end_fragment_id = self.resolve_fragment_id(edit.end_id, edit.end_offset)?;
1293
1294 let mut fragments_cursor = self.fragments.cursor::<FragmentIdRef, ()>();
1295
1296 if edit.start_id == edit.end_id && edit.start_offset == edit.end_offset {
1297 let splits = &self.insertion_splits[&undo.edit_id];
1298 let mut insertion_splits = splits.cursor::<(), ()>().map(|s| &s.fragment_id).peekable();
1299
1300 let first_split_id = insertion_splits.next().unwrap();
1301 new_fragments =
1302 fragments_cursor.slice(&FragmentIdRef::new(first_split_id), SeekBias::Left, &());
1303 new_ropes.push_tree(new_fragments.summary().text);
1304
1305 loop {
1306 let mut fragment = fragments_cursor.item().unwrap().clone();
1307 let was_visible = fragment.visible;
1308 fragment.visible = fragment.is_visible(&self.undo_map);
1309 fragment.max_undos.observe(undo.id);
1310
1311 new_ropes.push_fragment(&fragment, was_visible);
1312 new_fragments.push(fragment.clone(), &());
1313
1314 fragments_cursor.next();
1315 if let Some(split_id) = insertion_splits.next() {
1316 let slice =
1317 fragments_cursor.slice(&FragmentIdRef::new(split_id), SeekBias::Left, &());
1318 new_ropes.push_tree(slice.summary().text);
1319 new_fragments.push_tree(slice, &());
1320 } else {
1321 break;
1322 }
1323 }
1324 } else {
1325 new_fragments = fragments_cursor.slice(
1326 &FragmentIdRef::new(&start_fragment_id),
1327 SeekBias::Left,
1328 &(),
1329 );
1330 new_ropes.push_tree(new_fragments.summary().text);
1331
1332 while let Some(fragment) = fragments_cursor.item() {
1333 if fragment.id > end_fragment_id {
1334 break;
1335 } else {
1336 let mut fragment = fragment.clone();
1337 let fragment_was_visible = fragment.visible;
1338 if edit.version_in_range.observed(fragment.insertion.id)
1339 || fragment.insertion.id == undo.edit_id
1340 {
1341 fragment.visible = fragment.is_visible(&self.undo_map);
1342 fragment.max_undos.observe(undo.id);
1343 }
1344
1345 new_ropes.push_fragment(&fragment, fragment_was_visible);
1346 new_fragments.push(fragment, &());
1347 fragments_cursor.next();
1348 }
1349 }
1350 }
1351
1352 new_fragments.push_tree(fragments_cursor.suffix(&()), &());
1353 let (visible_text, deleted_text) = new_ropes.finish();
1354 drop(fragments_cursor);
1355
1356 self.fragments = new_fragments;
1357 self.visible_text = visible_text;
1358 self.deleted_text = deleted_text;
1359
1360 Ok(())
1361 }
1362
1363 fn flush_deferred_ops(&mut self) -> Result<()> {
1364 self.deferred_replicas.clear();
1365 let mut deferred_ops = Vec::new();
1366 for op in self.deferred_ops.drain().cursor().cloned() {
1367 if self.can_apply_op(&op) {
1368 self.apply_op(op)?;
1369 } else {
1370 self.deferred_replicas.insert(op.replica_id());
1371 deferred_ops.push(op);
1372 }
1373 }
1374 self.deferred_ops.insert(deferred_ops);
1375 Ok(())
1376 }
1377
1378 fn can_apply_op(&self, op: &Operation) -> bool {
1379 if self.deferred_replicas.contains(&op.replica_id()) {
1380 false
1381 } else {
1382 match op {
1383 Operation::Edit { edit, .. } => {
1384 self.version.observed(edit.start_id)
1385 && self.version.observed(edit.end_id)
1386 && edit.version_in_range <= self.version
1387 }
1388 Operation::Undo { undo, .. } => self.version.observed(undo.edit_id),
1389 Operation::UpdateSelections { selections, .. } => {
1390 if let Some(selections) = selections {
1391 selections.iter().all(|selection| {
1392 let contains_start = match selection.start {
1393 Anchor::Middle { insertion_id, .. } => {
1394 self.version.observed(insertion_id)
1395 }
1396 _ => true,
1397 };
1398 let contains_end = match selection.end {
1399 Anchor::Middle { insertion_id, .. } => {
1400 self.version.observed(insertion_id)
1401 }
1402 _ => true,
1403 };
1404 contains_start && contains_end
1405 })
1406 } else {
1407 true
1408 }
1409 }
1410 }
1411 }
1412 }
1413
1414 fn resolve_fragment_id(&self, edit_id: time::Local, offset: usize) -> Result<FragmentId> {
1415 let split_tree = self
1416 .insertion_splits
1417 .get(&edit_id)
1418 .ok_or_else(|| anyhow!("invalid operation"))?;
1419 let mut cursor = split_tree.cursor::<usize, ()>();
1420 cursor.seek(&offset, SeekBias::Left, &());
1421 Ok(cursor
1422 .item()
1423 .ok_or_else(|| anyhow!("invalid operation"))?
1424 .fragment_id
1425 .clone())
1426 }
1427
1428 fn splice_fragments<I>(&mut self, mut old_ranges: I, new_text: Option<String>) -> Vec<Operation>
1429 where
1430 I: Iterator<Item = Range<usize>>,
1431 {
1432 let mut cur_range = old_ranges.next();
1433 if cur_range.is_none() {
1434 return Vec::new();
1435 }
1436
1437 let mut ops = Vec::with_capacity(old_ranges.size_hint().0);
1438
1439 let mut old_fragments = SumTree::new();
1440 let mut old_visible_text = Rope::new();
1441 let mut old_deleted_text = Rope::new();
1442 mem::swap(&mut old_visible_text, &mut self.visible_text);
1443 mem::swap(&mut old_deleted_text, &mut self.deleted_text);
1444 mem::swap(&mut old_fragments, &mut self.fragments);
1445
1446 let mut fragments_cursor = old_fragments.cursor::<usize, usize>();
1447 let mut new_fragments =
1448 fragments_cursor.slice(&cur_range.as_ref().unwrap().start, SeekBias::Right, &());
1449
1450 let mut new_ropes =
1451 RopeBuilder::new(old_visible_text.cursor(0), old_deleted_text.cursor(0));
1452 new_ropes.push_tree(new_fragments.summary().text);
1453
1454 let mut start_id = None;
1455 let mut start_offset = None;
1456 let mut end_id = None;
1457 let mut end_offset = None;
1458 let mut version_in_range = time::Global::new();
1459
1460 let mut local_timestamp = self.local_clock.tick();
1461 let mut lamport_timestamp = self.lamport_clock.tick();
1462
1463 while cur_range.is_some() && fragments_cursor.item().is_some() {
1464 let mut fragment = fragments_cursor.item().unwrap().clone();
1465 let fragment_summary = fragments_cursor.item_summary().unwrap();
1466 let mut fragment_start = *fragments_cursor.start();
1467 let mut fragment_end = fragment_start + fragment.visible_len();
1468 let fragment_was_visible = fragment.visible;
1469
1470 let old_split_tree = self
1471 .insertion_splits
1472 .remove(&fragment.insertion.id)
1473 .unwrap();
1474 let mut splits_cursor = old_split_tree.cursor::<usize, ()>();
1475 let mut new_split_tree =
1476 splits_cursor.slice(&fragment.range_in_insertion.start, SeekBias::Right, &());
1477
1478 // Find all splices that start or end within the current fragment. Then, split the
1479 // fragment and reassemble it in both trees accounting for the deleted and the newly
1480 // inserted text.
1481 while cur_range.as_ref().map_or(false, |r| r.start < fragment_end) {
1482 let range = cur_range.clone().unwrap();
1483 if range.start > fragment_start {
1484 let mut prefix = fragment.clone();
1485 prefix.range_in_insertion.end =
1486 prefix.range_in_insertion.start + (range.start - fragment_start);
1487 prefix.id =
1488 FragmentId::between(&new_fragments.last().unwrap().id, &fragment.id);
1489 fragment.range_in_insertion.start = prefix.range_in_insertion.end;
1490
1491 new_ropes.push_fragment(&prefix, prefix.visible);
1492 new_fragments.push(prefix.clone(), &());
1493 new_split_tree.push(
1494 InsertionSplit {
1495 extent: prefix.range_in_insertion.end - prefix.range_in_insertion.start,
1496 fragment_id: prefix.id,
1497 },
1498 &(),
1499 );
1500 fragment_start = range.start;
1501 }
1502
1503 if range.end == fragment_start {
1504 end_id = Some(new_fragments.last().unwrap().insertion.id);
1505 end_offset = Some(new_fragments.last().unwrap().range_in_insertion.end);
1506 } else if range.end == fragment_end {
1507 end_id = Some(fragment.insertion.id);
1508 end_offset = Some(fragment.range_in_insertion.end);
1509 }
1510
1511 if range.start == fragment_start {
1512 start_id = Some(new_fragments.last().unwrap().insertion.id);
1513 start_offset = Some(new_fragments.last().unwrap().range_in_insertion.end);
1514
1515 if let Some(new_text) = new_text.clone() {
1516 let new_fragment = self.build_fragment_to_insert(
1517 &new_fragments.last().unwrap(),
1518 Some(&fragment),
1519 &new_text,
1520 local_timestamp,
1521 lamport_timestamp,
1522 );
1523
1524 new_ropes.push_str(&new_text);
1525 new_fragments.push(new_fragment, &());
1526 }
1527 }
1528
1529 if range.end < fragment_end {
1530 if range.end > fragment_start {
1531 let mut prefix = fragment.clone();
1532 prefix.range_in_insertion.end =
1533 prefix.range_in_insertion.start + (range.end - fragment_start);
1534 prefix.id =
1535 FragmentId::between(&new_fragments.last().unwrap().id, &fragment.id);
1536 version_in_range.observe_all(&fragment_summary.max_version);
1537 if prefix.visible {
1538 prefix.deletions.insert(local_timestamp);
1539 prefix.visible = false;
1540 }
1541 fragment.range_in_insertion.start = prefix.range_in_insertion.end;
1542 new_ropes.push_fragment(&prefix, fragment_was_visible);
1543 new_fragments.push(prefix.clone(), &());
1544 new_split_tree.push(
1545 InsertionSplit {
1546 extent: prefix.range_in_insertion.end
1547 - prefix.range_in_insertion.start,
1548 fragment_id: prefix.id,
1549 },
1550 &(),
1551 );
1552 fragment_start = range.end;
1553 end_id = Some(fragment.insertion.id);
1554 end_offset = Some(fragment.range_in_insertion.start);
1555 }
1556 } else {
1557 version_in_range.observe_all(&fragment_summary.max_version);
1558 if fragment.visible {
1559 fragment.deletions.insert(local_timestamp);
1560 fragment.visible = false;
1561 }
1562 }
1563
1564 // If the splice ends inside this fragment, we can advance to the next splice and
1565 // check if it also intersects the current fragment. Otherwise we break out of the
1566 // loop and find the first fragment that the splice does not contain fully.
1567 if range.end <= fragment_end {
1568 ops.push(Operation::Edit {
1569 edit: EditOperation {
1570 id: local_timestamp,
1571 start_id: start_id.unwrap(),
1572 start_offset: start_offset.unwrap(),
1573 end_id: end_id.unwrap(),
1574 end_offset: end_offset.unwrap(),
1575 version_in_range,
1576 new_text: new_text.clone(),
1577 },
1578 lamport_timestamp,
1579 });
1580
1581 start_id = None;
1582 start_offset = None;
1583 end_id = None;
1584 end_offset = None;
1585 version_in_range = time::Global::new();
1586 cur_range = old_ranges.next();
1587 if cur_range.is_some() {
1588 local_timestamp = self.local_clock.tick();
1589 lamport_timestamp = self.lamport_clock.tick();
1590 }
1591 } else {
1592 break;
1593 }
1594 }
1595 new_split_tree.push(
1596 InsertionSplit {
1597 extent: fragment.range_in_insertion.end - fragment.range_in_insertion.start,
1598 fragment_id: fragment.id.clone(),
1599 },
1600 &(),
1601 );
1602 splits_cursor.next();
1603 new_split_tree.push_tree(
1604 splits_cursor.slice(&old_split_tree.extent::<usize>(), SeekBias::Right, &()),
1605 &(),
1606 );
1607 self.insertion_splits
1608 .insert(fragment.insertion.id, new_split_tree);
1609
1610 new_ropes.push_fragment(&fragment, fragment_was_visible);
1611 new_fragments.push(fragment, &());
1612
1613 // Scan forward until we find a fragment that is not fully contained by the current splice.
1614 fragments_cursor.next();
1615 if let Some(range) = cur_range.clone() {
1616 while let Some(fragment) = fragments_cursor.item() {
1617 let fragment_summary = fragments_cursor.item_summary().unwrap();
1618 let fragment_was_visible = fragment.visible;
1619 fragment_start = *fragments_cursor.start();
1620 fragment_end = fragment_start + fragment.visible_len();
1621 if range.start < fragment_start && range.end >= fragment_end {
1622 let mut new_fragment = fragment.clone();
1623 version_in_range.observe_all(&fragment_summary.max_version);
1624 if new_fragment.visible {
1625 new_fragment.deletions.insert(local_timestamp);
1626 new_fragment.visible = false;
1627 }
1628
1629 new_ropes.push_fragment(&new_fragment, fragment_was_visible);
1630 new_fragments.push(new_fragment, &());
1631 fragments_cursor.next();
1632
1633 if range.end == fragment_end {
1634 end_id = Some(fragment.insertion.id);
1635 end_offset = Some(fragment.range_in_insertion.end);
1636 ops.push(Operation::Edit {
1637 edit: EditOperation {
1638 id: local_timestamp,
1639 start_id: start_id.unwrap(),
1640 start_offset: start_offset.unwrap(),
1641 end_id: end_id.unwrap(),
1642 end_offset: end_offset.unwrap(),
1643 version_in_range,
1644 new_text: new_text.clone(),
1645 },
1646 lamport_timestamp,
1647 });
1648
1649 start_id = None;
1650 start_offset = None;
1651 end_id = None;
1652 end_offset = None;
1653 version_in_range = time::Global::new();
1654
1655 cur_range = old_ranges.next();
1656 if cur_range.is_some() {
1657 local_timestamp = self.local_clock.tick();
1658 lamport_timestamp = self.lamport_clock.tick();
1659 }
1660 break;
1661 }
1662 } else {
1663 break;
1664 }
1665 }
1666
1667 // If the splice we are currently evaluating starts after the end of the fragment
1668 // that the cursor is parked at, we should seek to the next splice's start range
1669 // and push all the fragments in between into the new tree.
1670 if cur_range.as_ref().map_or(false, |r| r.start > fragment_end) {
1671 let slice = fragments_cursor.slice(
1672 &cur_range.as_ref().unwrap().start,
1673 SeekBias::Right,
1674 &(),
1675 );
1676 new_ropes.push_tree(slice.summary().text);
1677 new_fragments.push_tree(slice, &());
1678 }
1679 }
1680 }
1681
1682 // Handle range that is at the end of the buffer if it exists. There should never be
1683 // multiple because ranges must be disjoint.
1684 if cur_range.is_some() {
1685 debug_assert_eq!(old_ranges.next(), None);
1686 let last_fragment = new_fragments.last().unwrap();
1687 ops.push(Operation::Edit {
1688 edit: EditOperation {
1689 id: local_timestamp,
1690 start_id: last_fragment.insertion.id,
1691 start_offset: last_fragment.range_in_insertion.end,
1692 end_id: last_fragment.insertion.id,
1693 end_offset: last_fragment.range_in_insertion.end,
1694 version_in_range: time::Global::new(),
1695 // TODO: avoid cloning the String.
1696 new_text: new_text.clone(),
1697 },
1698 lamport_timestamp,
1699 });
1700
1701 if let Some(new_text) = new_text {
1702 let new_fragment = self.build_fragment_to_insert(
1703 &last_fragment,
1704 None,
1705 &new_text,
1706 local_timestamp,
1707 lamport_timestamp,
1708 );
1709
1710 new_ropes.push_str(&new_text);
1711 new_fragments.push(new_fragment, &());
1712 }
1713 }
1714
1715 new_fragments.push_tree(fragments_cursor.suffix(&()), &());
1716 let (visible_text, deleted_text) = new_ropes.finish();
1717
1718 self.fragments = new_fragments;
1719 self.visible_text = visible_text;
1720 self.deleted_text = deleted_text;
1721 ops
1722 }
1723
1724 fn split_fragment(
1725 &mut self,
1726 prev_fragment: &Fragment,
1727 fragment: &Fragment,
1728 range: Range<usize>,
1729 ) -> (Option<Fragment>, Option<Fragment>, Option<Fragment>) {
1730 debug_assert!(range.start >= fragment.range_in_insertion.start);
1731 debug_assert!(range.start <= fragment.range_in_insertion.end);
1732 debug_assert!(range.end <= fragment.range_in_insertion.end);
1733 debug_assert!(range.end >= fragment.range_in_insertion.start);
1734
1735 if range.end == fragment.range_in_insertion.start {
1736 (None, None, Some(fragment.clone()))
1737 } else if range.start == fragment.range_in_insertion.end {
1738 (Some(fragment.clone()), None, None)
1739 } else if range.start == fragment.range_in_insertion.start
1740 && range.end == fragment.range_in_insertion.end
1741 {
1742 (None, Some(fragment.clone()), None)
1743 } else {
1744 let mut prefix = fragment.clone();
1745
1746 let after_range = if range.end < fragment.range_in_insertion.end {
1747 let mut suffix = prefix.clone();
1748 suffix.range_in_insertion.start = range.end;
1749 prefix.range_in_insertion.end = range.end;
1750 prefix.id = FragmentId::between(&prev_fragment.id, &suffix.id);
1751 Some(suffix)
1752 } else {
1753 None
1754 };
1755
1756 let within_range = if range.start != range.end {
1757 let mut suffix = prefix.clone();
1758 suffix.range_in_insertion.start = range.start;
1759 prefix.range_in_insertion.end = range.start;
1760 prefix.id = FragmentId::between(&prev_fragment.id, &suffix.id);
1761 Some(suffix)
1762 } else {
1763 None
1764 };
1765
1766 let before_range = if range.start > fragment.range_in_insertion.start {
1767 Some(prefix)
1768 } else {
1769 None
1770 };
1771
1772 let old_split_tree = self
1773 .insertion_splits
1774 .remove(&fragment.insertion.id)
1775 .unwrap();
1776 let mut cursor = old_split_tree.cursor::<usize, ()>();
1777 let mut new_split_tree =
1778 cursor.slice(&fragment.range_in_insertion.start, SeekBias::Right, &());
1779
1780 if let Some(ref fragment) = before_range {
1781 new_split_tree.push(
1782 InsertionSplit {
1783 extent: range.start - fragment.range_in_insertion.start,
1784 fragment_id: fragment.id.clone(),
1785 },
1786 &(),
1787 );
1788 }
1789
1790 if let Some(ref fragment) = within_range {
1791 new_split_tree.push(
1792 InsertionSplit {
1793 extent: range.end - range.start,
1794 fragment_id: fragment.id.clone(),
1795 },
1796 &(),
1797 );
1798 }
1799
1800 if let Some(ref fragment) = after_range {
1801 new_split_tree.push(
1802 InsertionSplit {
1803 extent: fragment.range_in_insertion.end - range.end,
1804 fragment_id: fragment.id.clone(),
1805 },
1806 &(),
1807 );
1808 }
1809
1810 cursor.next();
1811 new_split_tree.push_tree(
1812 cursor.slice(&old_split_tree.extent::<usize>(), SeekBias::Right, &()),
1813 &(),
1814 );
1815
1816 self.insertion_splits
1817 .insert(fragment.insertion.id, new_split_tree);
1818
1819 (before_range, within_range, after_range)
1820 }
1821 }
1822
1823 fn build_fragment_to_insert(
1824 &mut self,
1825 prev_fragment: &Fragment,
1826 next_fragment: Option<&Fragment>,
1827 text: &str,
1828 insertion_id: time::Local,
1829 lamport_timestamp: time::Lamport,
1830 ) -> Fragment {
1831 let new_fragment_id = FragmentId::between(
1832 &prev_fragment.id,
1833 next_fragment
1834 .map(|f| &f.id)
1835 .unwrap_or(&FragmentId::max_value()),
1836 );
1837
1838 let range_in_insertion = 0..text.len();
1839 let mut split_tree = SumTree::new();
1840 split_tree.push(
1841 InsertionSplit {
1842 extent: range_in_insertion.len(),
1843 fragment_id: new_fragment_id.clone(),
1844 },
1845 &(),
1846 );
1847 self.insertion_splits.insert(insertion_id, split_tree);
1848
1849 Fragment::new(
1850 new_fragment_id,
1851 Arc::new(Insertion {
1852 id: insertion_id,
1853 parent_id: prev_fragment.insertion.id,
1854 offset_in_parent: prev_fragment.range_in_insertion.end,
1855 lamport_timestamp,
1856 }),
1857 range_in_insertion,
1858 )
1859 }
1860
1861 pub fn anchor_before<T: ToOffset>(&self, position: T) -> Anchor {
1862 self.anchor_at(position, AnchorBias::Left)
1863 }
1864
1865 pub fn anchor_after<T: ToOffset>(&self, position: T) -> Anchor {
1866 self.anchor_at(position, AnchorBias::Right)
1867 }
1868
1869 pub fn anchor_at<T: ToOffset>(&self, position: T, bias: AnchorBias) -> Anchor {
1870 let offset = position.to_offset(self);
1871 let max_offset = self.len();
1872 assert!(offset <= max_offset, "offset is out of range");
1873
1874 let seek_bias;
1875 match bias {
1876 AnchorBias::Left => {
1877 if offset == 0 {
1878 return Anchor::Start;
1879 } else {
1880 seek_bias = SeekBias::Left;
1881 }
1882 }
1883 AnchorBias::Right => {
1884 if offset == max_offset {
1885 return Anchor::End;
1886 } else {
1887 seek_bias = SeekBias::Right;
1888 }
1889 }
1890 };
1891
1892 let mut cursor = self.fragments.cursor::<usize, usize>();
1893 cursor.seek(&offset, seek_bias, &());
1894 let fragment = cursor.item().unwrap();
1895 let offset_in_fragment = offset - cursor.start();
1896 let offset_in_insertion = fragment.range_in_insertion.start + offset_in_fragment;
1897 let anchor = Anchor::Middle {
1898 insertion_id: fragment.insertion.id,
1899 offset: offset_in_insertion,
1900 bias,
1901 };
1902 anchor
1903 }
1904
1905 fn fragment_id_for_anchor(&self, anchor: &Anchor) -> Result<&FragmentId> {
1906 match anchor {
1907 Anchor::Start => Ok(FragmentId::max_value()),
1908 Anchor::End => Ok(FragmentId::min_value()),
1909 Anchor::Middle {
1910 insertion_id,
1911 offset,
1912 bias,
1913 ..
1914 } => {
1915 let seek_bias = match bias {
1916 AnchorBias::Left => SeekBias::Left,
1917 AnchorBias::Right => SeekBias::Right,
1918 };
1919
1920 let splits = self
1921 .insertion_splits
1922 .get(&insertion_id)
1923 .ok_or_else(|| anyhow!("split does not exist for insertion id"))?;
1924 let mut splits_cursor = splits.cursor::<usize, ()>();
1925 splits_cursor.seek(offset, seek_bias, &());
1926 splits_cursor
1927 .item()
1928 .ok_or_else(|| anyhow!("split offset is out of range"))
1929 .map(|split| &split.fragment_id)
1930 }
1931 }
1932 }
1933
1934 fn summary_for_anchor(&self, anchor: &Anchor) -> TextSummary {
1935 match anchor {
1936 Anchor::Start => TextSummary::default(),
1937 Anchor::End => self.text_summary(),
1938 Anchor::Middle {
1939 insertion_id,
1940 offset,
1941 bias,
1942 } => {
1943 let seek_bias = match bias {
1944 AnchorBias::Left => SeekBias::Left,
1945 AnchorBias::Right => SeekBias::Right,
1946 };
1947
1948 let splits = self
1949 .insertion_splits
1950 .get(&insertion_id)
1951 .expect("split does not exist for insertion id");
1952 let mut splits_cursor = splits.cursor::<usize, ()>();
1953 splits_cursor.seek(offset, seek_bias, &());
1954 let split = splits_cursor.item().expect("split offset is out of range");
1955
1956 let mut fragments_cursor = self.fragments.cursor::<FragmentIdRef, usize>();
1957 fragments_cursor.seek(&FragmentIdRef::new(&split.fragment_id), SeekBias::Left, &());
1958 let fragment = fragments_cursor.item().expect("fragment id does not exist");
1959
1960 let mut ix = *fragments_cursor.start();
1961 if fragment.visible {
1962 ix += offset - fragment.range_in_insertion.start;
1963 }
1964 self.text_summary_for_range(0..ix)
1965 }
1966 }
1967 }
1968
1969 pub fn point_for_offset(&self, offset: usize) -> Result<Point> {
1970 if offset <= self.len() {
1971 Ok(self.text_summary_for_range(0..offset).lines)
1972 } else {
1973 Err(anyhow!("offset out of bounds"))
1974 }
1975 }
1976
1977 pub fn clip_point(&self, point: Point, bias: Bias) -> Point {
1978 self.visible_text.clip_point(point, bias)
1979 }
1980
1981 pub fn clip_offset(&self, offset: usize, bias: Bias) -> usize {
1982 self.visible_text.clip_offset(offset, bias)
1983 }
1984}
1985
1986impl Clone for Buffer {
1987 fn clone(&self) -> Self {
1988 Self {
1989 fragments: self.fragments.clone(),
1990 visible_text: self.visible_text.clone(),
1991 deleted_text: self.deleted_text.clone(),
1992 insertion_splits: self.insertion_splits.clone(),
1993 version: self.version.clone(),
1994 saved_version: self.saved_version.clone(),
1995 saved_mtime: self.saved_mtime,
1996 last_edit: self.last_edit.clone(),
1997 undo_map: self.undo_map.clone(),
1998 history: self.history.clone(),
1999 selections: self.selections.clone(),
2000 selections_last_update: self.selections_last_update.clone(),
2001 deferred_ops: self.deferred_ops.clone(),
2002 file: self.file.clone(),
2003 language: self.language.clone(),
2004 tree: self.tree.clone(),
2005 is_parsing: false,
2006 deferred_replicas: self.deferred_replicas.clone(),
2007 replica_id: self.replica_id,
2008 local_clock: self.local_clock.clone(),
2009 lamport_clock: self.lamport_clock.clone(),
2010 }
2011 }
2012}
2013
2014struct RopeBuilder<'a> {
2015 old_visible_cursor: rope::Cursor<'a>,
2016 old_deleted_cursor: rope::Cursor<'a>,
2017 new_visible: Rope,
2018 new_deleted: Rope,
2019}
2020
2021impl<'a> RopeBuilder<'a> {
2022 fn new(old_visible_cursor: rope::Cursor<'a>, old_deleted_cursor: rope::Cursor<'a>) -> Self {
2023 Self {
2024 old_visible_cursor,
2025 old_deleted_cursor,
2026 new_visible: Rope::new(),
2027 new_deleted: Rope::new(),
2028 }
2029 }
2030
2031 fn push_tree(&mut self, len: FragmentTextSummary) {
2032 self.push(len.visible, true, true);
2033 self.push(len.deleted, false, false);
2034 }
2035
2036 fn push_fragment(&mut self, fragment: &Fragment, was_visible: bool) {
2037 self.push(fragment.len(), was_visible, fragment.visible)
2038 }
2039
2040 fn push(&mut self, len: usize, was_visible: bool, is_visible: bool) {
2041 let text = if was_visible {
2042 self.old_visible_cursor
2043 .slice(self.old_visible_cursor.offset() + len)
2044 } else {
2045 self.old_deleted_cursor
2046 .slice(self.old_deleted_cursor.offset() + len)
2047 };
2048 if is_visible {
2049 self.new_visible.append(text);
2050 } else {
2051 self.new_deleted.append(text);
2052 }
2053 }
2054
2055 fn push_str(&mut self, text: &str) {
2056 self.new_visible.push(text);
2057 }
2058
2059 fn finish(mut self) -> (Rope, Rope) {
2060 self.new_visible.append(self.old_visible_cursor.suffix());
2061 self.new_deleted.append(self.old_deleted_cursor.suffix());
2062 (self.new_visible, self.new_deleted)
2063 }
2064}
2065
2066#[derive(Clone, Debug, Eq, PartialEq)]
2067pub enum Event {
2068 Edited,
2069 Dirtied,
2070 Saved,
2071 FileHandleChanged,
2072 Reloaded,
2073 Reparsed,
2074}
2075
2076impl Entity for Buffer {
2077 type Event = Event;
2078}
2079
2080impl<'a, F: Fn(&FragmentSummary) -> bool> Iterator for Edits<'a, F> {
2081 type Item = Edit;
2082
2083 fn next(&mut self) -> Option<Self::Item> {
2084 let mut change: Option<Edit> = None;
2085
2086 while let Some(fragment) = self.cursor.item() {
2087 let new_offset = self.cursor.start().visible;
2088 let old_offset = (new_offset as isize - self.delta) as usize;
2089
2090 if !fragment.was_visible(&self.since, &self.undos) && fragment.visible {
2091 if let Some(ref mut change) = change {
2092 if change.new_range.end == new_offset {
2093 change.new_range.end += fragment.len();
2094 self.delta += fragment.len() as isize;
2095 } else {
2096 break;
2097 }
2098 } else {
2099 change = Some(Edit {
2100 old_range: old_offset..old_offset,
2101 new_range: new_offset..new_offset + fragment.len(),
2102 old_lines: Point::zero(),
2103 });
2104 self.delta += fragment.len() as isize;
2105 }
2106 } else if fragment.was_visible(&self.since, &self.undos) && !fragment.visible {
2107 let deleted_start = self.cursor.start().deleted;
2108 let old_lines = self.deleted_text.to_point(deleted_start + fragment.len())
2109 - self.deleted_text.to_point(deleted_start);
2110 if let Some(ref mut change) = change {
2111 if change.new_range.end == new_offset {
2112 change.old_range.end += fragment.len();
2113 change.old_lines += &old_lines;
2114 self.delta -= fragment.len() as isize;
2115 } else {
2116 break;
2117 }
2118 } else {
2119 change = Some(Edit {
2120 old_range: old_offset..old_offset + fragment.len(),
2121 new_range: new_offset..new_offset,
2122 old_lines,
2123 });
2124 self.delta -= fragment.len() as isize;
2125 }
2126 }
2127
2128 self.cursor.next();
2129 }
2130
2131 change
2132 }
2133}
2134
2135#[derive(Ord, PartialOrd, Eq, PartialEq, Clone, Debug)]
2136struct FragmentId(Arc<[u16]>);
2137
2138lazy_static! {
2139 static ref FRAGMENT_ID_EMPTY: FragmentId = FragmentId(Arc::from([]));
2140 static ref FRAGMENT_ID_MIN_VALUE: FragmentId = FragmentId(Arc::from([0 as u16]));
2141 static ref FRAGMENT_ID_MAX_VALUE: FragmentId = FragmentId(Arc::from([u16::max_value()]));
2142}
2143
2144impl Default for FragmentId {
2145 fn default() -> Self {
2146 FRAGMENT_ID_EMPTY.clone()
2147 }
2148}
2149
2150impl FragmentId {
2151 fn min_value() -> &'static Self {
2152 &FRAGMENT_ID_MIN_VALUE
2153 }
2154
2155 fn max_value() -> &'static Self {
2156 &FRAGMENT_ID_MAX_VALUE
2157 }
2158
2159 fn between(left: &Self, right: &Self) -> Self {
2160 Self::between_with_max(left, right, u16::max_value())
2161 }
2162
2163 fn between_with_max(left: &Self, right: &Self, max_value: u16) -> Self {
2164 let mut new_entries = Vec::new();
2165
2166 let left_entries = left.0.iter().cloned().chain(iter::repeat(0));
2167 let right_entries = right.0.iter().cloned().chain(iter::repeat(max_value));
2168 for (l, r) in left_entries.zip(right_entries) {
2169 let interval = r - l;
2170 if interval > 1 {
2171 new_entries.push(l + cmp::max(1, cmp::min(8, interval / 2)));
2172 break;
2173 } else {
2174 new_entries.push(l);
2175 }
2176 }
2177
2178 FragmentId(Arc::from(new_entries))
2179 }
2180}
2181
2182#[derive(Ord, PartialOrd, Eq, PartialEq, Clone, Debug, Default)]
2183struct FragmentIdRef<'a>(Option<&'a FragmentId>);
2184
2185impl<'a> FragmentIdRef<'a> {
2186 fn new(id: &'a FragmentId) -> Self {
2187 Self(Some(id))
2188 }
2189}
2190
2191impl<'a> sum_tree::Dimension<'a, FragmentSummary> for FragmentIdRef<'a> {
2192 fn add_summary(&mut self, summary: &'a FragmentSummary) {
2193 self.0 = Some(&summary.max_fragment_id)
2194 }
2195}
2196
2197impl Fragment {
2198 fn new(id: FragmentId, insertion: Arc<Insertion>, range_in_insertion: Range<usize>) -> Self {
2199 Self {
2200 id,
2201 insertion,
2202 range_in_insertion,
2203 deletions: Default::default(),
2204 max_undos: Default::default(),
2205 visible: true,
2206 }
2207 }
2208
2209 fn is_visible(&self, undos: &UndoMap) -> bool {
2210 !undos.is_undone(self.insertion.id) && self.deletions.iter().all(|d| undos.is_undone(*d))
2211 }
2212
2213 fn was_visible(&self, version: &time::Global, undos: &UndoMap) -> bool {
2214 (version.observed(self.insertion.id) && !undos.was_undone(self.insertion.id, version))
2215 && self
2216 .deletions
2217 .iter()
2218 .all(|d| !version.observed(*d) || undos.was_undone(*d, version))
2219 }
2220
2221 fn len(&self) -> usize {
2222 self.range_in_insertion.len()
2223 }
2224
2225 fn visible_len(&self) -> usize {
2226 if self.visible {
2227 self.range_in_insertion.len()
2228 } else {
2229 0
2230 }
2231 }
2232}
2233
2234impl sum_tree::Item for Fragment {
2235 type Summary = FragmentSummary;
2236
2237 fn summary(&self) -> Self::Summary {
2238 let mut max_version = time::Global::new();
2239 max_version.observe(self.insertion.id);
2240 for deletion in &self.deletions {
2241 max_version.observe(*deletion);
2242 }
2243 max_version.observe_all(&self.max_undos);
2244
2245 if self.visible {
2246 FragmentSummary {
2247 text: FragmentTextSummary {
2248 visible: self.len(),
2249 deleted: 0,
2250 },
2251 max_fragment_id: self.id.clone(),
2252 max_version,
2253 }
2254 } else {
2255 FragmentSummary {
2256 text: FragmentTextSummary {
2257 visible: 0,
2258 deleted: self.len(),
2259 },
2260 max_fragment_id: self.id.clone(),
2261 max_version,
2262 }
2263 }
2264 }
2265}
2266
2267impl sum_tree::Summary for FragmentSummary {
2268 type Context = ();
2269
2270 fn add_summary(&mut self, other: &Self, _: &Self::Context) {
2271 self.text.visible += &other.text.visible;
2272 self.text.deleted += &other.text.deleted;
2273 debug_assert!(self.max_fragment_id <= other.max_fragment_id);
2274 self.max_fragment_id = other.max_fragment_id.clone();
2275 self.max_version.observe_all(&other.max_version);
2276 }
2277}
2278
2279impl Default for FragmentSummary {
2280 fn default() -> Self {
2281 FragmentSummary {
2282 text: FragmentTextSummary::default(),
2283 max_fragment_id: FragmentId::min_value().clone(),
2284 max_version: time::Global::new(),
2285 }
2286 }
2287}
2288
2289impl<'a> sum_tree::Dimension<'a, FragmentSummary> for usize {
2290 fn add_summary(&mut self, summary: &FragmentSummary) {
2291 *self += summary.text.visible;
2292 }
2293}
2294
2295impl sum_tree::Item for InsertionSplit {
2296 type Summary = InsertionSplitSummary;
2297
2298 fn summary(&self) -> Self::Summary {
2299 InsertionSplitSummary {
2300 extent: self.extent,
2301 }
2302 }
2303}
2304
2305impl sum_tree::Summary for InsertionSplitSummary {
2306 type Context = ();
2307
2308 fn add_summary(&mut self, other: &Self, _: &()) {
2309 self.extent += other.extent;
2310 }
2311}
2312
2313impl Default for InsertionSplitSummary {
2314 fn default() -> Self {
2315 InsertionSplitSummary { extent: 0 }
2316 }
2317}
2318
2319impl<'a> sum_tree::Dimension<'a, InsertionSplitSummary> for usize {
2320 fn add_summary(&mut self, summary: &InsertionSplitSummary) {
2321 *self += summary.extent;
2322 }
2323}
2324
2325impl Operation {
2326 fn replica_id(&self) -> ReplicaId {
2327 self.lamport_timestamp().replica_id
2328 }
2329
2330 fn lamport_timestamp(&self) -> time::Lamport {
2331 match self {
2332 Operation::Edit {
2333 lamport_timestamp, ..
2334 } => *lamport_timestamp,
2335 Operation::Undo {
2336 lamport_timestamp, ..
2337 } => *lamport_timestamp,
2338 Operation::UpdateSelections {
2339 lamport_timestamp, ..
2340 } => *lamport_timestamp,
2341 }
2342 }
2343
2344 pub fn is_edit(&self) -> bool {
2345 match self {
2346 Operation::Edit { .. } => true,
2347 _ => false,
2348 }
2349 }
2350}
2351
2352impl operation_queue::Operation for Operation {
2353 fn timestamp(&self) -> time::Lamport {
2354 self.lamport_timestamp()
2355 }
2356}
2357
2358pub trait ToOffset {
2359 fn to_offset(&self, buffer: &Buffer) -> usize;
2360}
2361
2362impl ToOffset for Point {
2363 fn to_offset(&self, buffer: &Buffer) -> usize {
2364 buffer.visible_text.to_offset(*self)
2365 }
2366}
2367
2368impl ToOffset for usize {
2369 fn to_offset(&self, _: &Buffer) -> usize {
2370 *self
2371 }
2372}
2373
2374impl ToOffset for Anchor {
2375 fn to_offset(&self, buffer: &Buffer) -> usize {
2376 buffer.summary_for_anchor(self).bytes
2377 }
2378}
2379
2380impl<'a> ToOffset for &'a Anchor {
2381 fn to_offset(&self, buffer: &Buffer) -> usize {
2382 buffer.summary_for_anchor(self).bytes
2383 }
2384}
2385
2386pub trait ToPoint {
2387 fn to_point(&self, buffer: &Buffer) -> Point;
2388}
2389
2390impl ToPoint for Anchor {
2391 fn to_point(&self, buffer: &Buffer) -> Point {
2392 buffer.summary_for_anchor(self).lines
2393 }
2394}
2395
2396impl ToPoint for usize {
2397 fn to_point(&self, buffer: &Buffer) -> Point {
2398 buffer.visible_text.to_point(*self)
2399 }
2400}
2401
2402#[cfg(test)]
2403mod tests {
2404 use super::*;
2405 use crate::{
2406 test::{build_app_state, temp_tree},
2407 util::RandomCharIter,
2408 worktree::{Worktree, WorktreeHandle},
2409 };
2410 use gpui::{App, ModelHandle};
2411 use rand::prelude::*;
2412 use serde_json::json;
2413 use std::{
2414 cell::RefCell,
2415 cmp::Ordering,
2416 fs,
2417 rc::Rc,
2418 sync::atomic::{self, AtomicUsize},
2419 };
2420
2421 #[gpui::test]
2422 fn test_edit(ctx: &mut gpui::MutableAppContext) {
2423 ctx.add_model(|ctx| {
2424 let mut buffer = Buffer::new(0, "abc", ctx);
2425 assert_eq!(buffer.text(), "abc");
2426 buffer.edit(vec![3..3], "def", None).unwrap();
2427 assert_eq!(buffer.text(), "abcdef");
2428 buffer.edit(vec![0..0], "ghi", None).unwrap();
2429 assert_eq!(buffer.text(), "ghiabcdef");
2430 buffer.edit(vec![5..5], "jkl", None).unwrap();
2431 assert_eq!(buffer.text(), "ghiabjklcdef");
2432 buffer.edit(vec![6..7], "", None).unwrap();
2433 assert_eq!(buffer.text(), "ghiabjlcdef");
2434 buffer.edit(vec![4..9], "mno", None).unwrap();
2435 assert_eq!(buffer.text(), "ghiamnoef");
2436 buffer
2437 });
2438 }
2439
2440 #[gpui::test]
2441 fn test_edit_events(app: &mut gpui::MutableAppContext) {
2442 let mut now = Instant::now();
2443 let buffer_1_events = Rc::new(RefCell::new(Vec::new()));
2444 let buffer_2_events = Rc::new(RefCell::new(Vec::new()));
2445
2446 let buffer1 = app.add_model(|ctx| Buffer::new(0, "abcdef", ctx));
2447 let buffer2 = app.add_model(|ctx| Buffer::new(1, "abcdef", ctx));
2448 let mut buffer_ops = Vec::new();
2449 buffer1.update(app, |buffer, ctx| {
2450 let buffer_1_events = buffer_1_events.clone();
2451 ctx.subscribe(&buffer1, move |_, event, _| {
2452 buffer_1_events.borrow_mut().push(event.clone())
2453 });
2454 let buffer_2_events = buffer_2_events.clone();
2455 ctx.subscribe(&buffer2, move |_, event, _| {
2456 buffer_2_events.borrow_mut().push(event.clone())
2457 });
2458
2459 // An edit emits an edited event, followed by a dirtied event,
2460 // since the buffer was previously in a clean state.
2461 let ops = buffer.edit(Some(2..4), "XYZ", Some(ctx)).unwrap();
2462 buffer_ops.extend_from_slice(&ops);
2463
2464 // An empty transaction does not emit any events.
2465 buffer.start_transaction(None).unwrap();
2466 buffer.end_transaction(None, Some(ctx)).unwrap();
2467
2468 // A transaction containing two edits emits one edited event.
2469 now += Duration::from_secs(1);
2470 buffer.start_transaction_at(None, now).unwrap();
2471 let ops = buffer.edit(Some(5..5), "u", Some(ctx)).unwrap();
2472 buffer_ops.extend_from_slice(&ops);
2473 let ops = buffer.edit(Some(6..6), "w", Some(ctx)).unwrap();
2474 buffer_ops.extend_from_slice(&ops);
2475 buffer.end_transaction_at(None, now, Some(ctx)).unwrap();
2476
2477 // Undoing a transaction emits one edited event.
2478 let ops = buffer.undo(Some(ctx));
2479 buffer_ops.extend_from_slice(&ops);
2480 });
2481
2482 // Incorporating a set of remote ops emits a single edited event,
2483 // followed by a dirtied event.
2484 buffer2.update(app, |buffer, ctx| {
2485 buffer.apply_ops(buffer_ops, Some(ctx)).unwrap();
2486 });
2487
2488 let buffer_1_events = buffer_1_events.borrow();
2489 assert_eq!(
2490 *buffer_1_events,
2491 vec![Event::Edited, Event::Dirtied, Event::Edited, Event::Edited]
2492 );
2493
2494 let buffer_2_events = buffer_2_events.borrow();
2495 assert_eq!(*buffer_2_events, vec![Event::Edited, Event::Dirtied]);
2496 }
2497
2498 #[gpui::test]
2499 fn test_random_edits(ctx: &mut gpui::MutableAppContext) {
2500 for seed in 0..100 {
2501 println!("{:?}", seed);
2502 let mut rng = &mut StdRng::seed_from_u64(seed);
2503
2504 let reference_string_len = rng.gen_range(0..3);
2505 let mut reference_string = RandomCharIter::new(&mut rng)
2506 .take(reference_string_len)
2507 .collect::<String>();
2508 ctx.add_model(|ctx| {
2509 let mut buffer = Buffer::new(0, reference_string.as_str(), ctx);
2510 let mut buffer_versions = Vec::new();
2511 for _i in 0..10 {
2512 let (old_ranges, new_text, _) = buffer.randomly_mutate(rng, None);
2513 for old_range in old_ranges.iter().rev() {
2514 reference_string.replace_range(old_range.clone(), &new_text);
2515 }
2516 assert_eq!(buffer.text(), reference_string);
2517
2518 if rng.gen_bool(0.25) {
2519 buffer.randomly_undo_redo(rng);
2520 reference_string = buffer.text();
2521 }
2522
2523 let range = buffer.random_byte_range(0, rng);
2524 assert_eq!(
2525 buffer.text_summary_for_range(range.clone()),
2526 TextSummary::from(&reference_string[range])
2527 );
2528
2529 if rng.gen_bool(0.3) {
2530 buffer_versions.push(buffer.clone());
2531 }
2532 }
2533
2534 for mut old_buffer in buffer_versions {
2535 let mut delta = 0_isize;
2536 for Edit {
2537 old_range,
2538 new_range,
2539 ..
2540 } in buffer.edits_since(old_buffer.version.clone())
2541 {
2542 let old_len = old_range.end - old_range.start;
2543 let new_len = new_range.end - new_range.start;
2544 let old_start = (old_range.start as isize + delta) as usize;
2545 let new_text: String = buffer.text_for_range(new_range).collect();
2546 old_buffer
2547 .edit(Some(old_start..old_start + old_len), new_text, None)
2548 .unwrap();
2549
2550 delta += new_len as isize - old_len as isize;
2551 }
2552 assert_eq!(old_buffer.text(), buffer.text());
2553 }
2554
2555 buffer
2556 });
2557 }
2558 }
2559
2560 #[gpui::test]
2561 fn test_line_len(ctx: &mut gpui::MutableAppContext) {
2562 ctx.add_model(|ctx| {
2563 let mut buffer = Buffer::new(0, "", ctx);
2564 buffer.edit(vec![0..0], "abcd\nefg\nhij", None).unwrap();
2565 buffer.edit(vec![12..12], "kl\nmno", None).unwrap();
2566 buffer.edit(vec![18..18], "\npqrs\n", None).unwrap();
2567 buffer.edit(vec![18..21], "\nPQ", None).unwrap();
2568
2569 assert_eq!(buffer.line_len(0), 4);
2570 assert_eq!(buffer.line_len(1), 3);
2571 assert_eq!(buffer.line_len(2), 5);
2572 assert_eq!(buffer.line_len(3), 3);
2573 assert_eq!(buffer.line_len(4), 4);
2574 assert_eq!(buffer.line_len(5), 0);
2575 buffer
2576 });
2577 }
2578
2579 #[gpui::test]
2580 fn test_text_summary_for_range(ctx: &mut gpui::MutableAppContext) {
2581 ctx.add_model(|ctx| {
2582 let buffer = Buffer::new(0, "ab\nefg\nhklm\nnopqrs\ntuvwxyz", ctx);
2583 assert_eq!(
2584 buffer.text_summary_for_range(1..3),
2585 TextSummary {
2586 bytes: 2,
2587 lines: Point::new(1, 0),
2588 first_line_chars: 1,
2589 last_line_chars: 0,
2590 longest_row: 0,
2591 longest_row_chars: 1,
2592 }
2593 );
2594 assert_eq!(
2595 buffer.text_summary_for_range(1..12),
2596 TextSummary {
2597 bytes: 11,
2598 lines: Point::new(3, 0),
2599 first_line_chars: 1,
2600 last_line_chars: 0,
2601 longest_row: 2,
2602 longest_row_chars: 4,
2603 }
2604 );
2605 assert_eq!(
2606 buffer.text_summary_for_range(0..20),
2607 TextSummary {
2608 bytes: 20,
2609 lines: Point::new(4, 1),
2610 first_line_chars: 2,
2611 last_line_chars: 1,
2612 longest_row: 3,
2613 longest_row_chars: 6,
2614 }
2615 );
2616 assert_eq!(
2617 buffer.text_summary_for_range(0..22),
2618 TextSummary {
2619 bytes: 22,
2620 lines: Point::new(4, 3),
2621 first_line_chars: 2,
2622 last_line_chars: 3,
2623 longest_row: 3,
2624 longest_row_chars: 6,
2625 }
2626 );
2627 assert_eq!(
2628 buffer.text_summary_for_range(7..22),
2629 TextSummary {
2630 bytes: 15,
2631 lines: Point::new(2, 3),
2632 first_line_chars: 4,
2633 last_line_chars: 3,
2634 longest_row: 1,
2635 longest_row_chars: 6,
2636 }
2637 );
2638 buffer
2639 });
2640 }
2641
2642 #[gpui::test]
2643 fn test_chars_at(ctx: &mut gpui::MutableAppContext) {
2644 ctx.add_model(|ctx| {
2645 let mut buffer = Buffer::new(0, "", ctx);
2646 buffer.edit(vec![0..0], "abcd\nefgh\nij", None).unwrap();
2647 buffer.edit(vec![12..12], "kl\nmno", None).unwrap();
2648 buffer.edit(vec![18..18], "\npqrs", None).unwrap();
2649 buffer.edit(vec![18..21], "\nPQ", None).unwrap();
2650
2651 let chars = buffer.chars_at(Point::new(0, 0));
2652 assert_eq!(chars.collect::<String>(), "abcd\nefgh\nijkl\nmno\nPQrs");
2653
2654 let chars = buffer.chars_at(Point::new(1, 0));
2655 assert_eq!(chars.collect::<String>(), "efgh\nijkl\nmno\nPQrs");
2656
2657 let chars = buffer.chars_at(Point::new(2, 0));
2658 assert_eq!(chars.collect::<String>(), "ijkl\nmno\nPQrs");
2659
2660 let chars = buffer.chars_at(Point::new(3, 0));
2661 assert_eq!(chars.collect::<String>(), "mno\nPQrs");
2662
2663 let chars = buffer.chars_at(Point::new(4, 0));
2664 assert_eq!(chars.collect::<String>(), "PQrs");
2665
2666 // Regression test:
2667 let mut buffer = Buffer::new(0, "", ctx);
2668 buffer.edit(vec![0..0], "[workspace]\nmembers = [\n \"xray_core\",\n \"xray_server\",\n \"xray_cli\",\n \"xray_wasm\",\n]\n", None).unwrap();
2669 buffer.edit(vec![60..60], "\n", None).unwrap();
2670
2671 let chars = buffer.chars_at(Point::new(6, 0));
2672 assert_eq!(chars.collect::<String>(), " \"xray_wasm\",\n]\n");
2673
2674 buffer
2675 });
2676 }
2677
2678 #[test]
2679 fn test_fragment_ids() {
2680 for seed in 0..10 {
2681 let rng = &mut StdRng::seed_from_u64(seed);
2682
2683 let mut ids = vec![FragmentId(Arc::from([0])), FragmentId(Arc::from([4]))];
2684 for _i in 0..100 {
2685 let index = rng.gen_range(1..ids.len());
2686
2687 let left = ids[index - 1].clone();
2688 let right = ids[index].clone();
2689 ids.insert(index, FragmentId::between_with_max(&left, &right, 4));
2690
2691 let mut sorted_ids = ids.clone();
2692 sorted_ids.sort();
2693 assert_eq!(ids, sorted_ids);
2694 }
2695 }
2696 }
2697
2698 #[gpui::test]
2699 fn test_anchors(ctx: &mut gpui::MutableAppContext) {
2700 ctx.add_model(|ctx| {
2701 let mut buffer = Buffer::new(0, "", ctx);
2702 buffer.edit(vec![0..0], "abc", None).unwrap();
2703 let left_anchor = buffer.anchor_before(2);
2704 let right_anchor = buffer.anchor_after(2);
2705
2706 buffer.edit(vec![1..1], "def\n", None).unwrap();
2707 assert_eq!(buffer.text(), "adef\nbc");
2708 assert_eq!(left_anchor.to_offset(&buffer), 6);
2709 assert_eq!(right_anchor.to_offset(&buffer), 6);
2710 assert_eq!(left_anchor.to_point(&buffer), Point { row: 1, column: 1 });
2711 assert_eq!(right_anchor.to_point(&buffer), Point { row: 1, column: 1 });
2712
2713 buffer.edit(vec![2..3], "", None).unwrap();
2714 assert_eq!(buffer.text(), "adf\nbc");
2715 assert_eq!(left_anchor.to_offset(&buffer), 5);
2716 assert_eq!(right_anchor.to_offset(&buffer), 5);
2717 assert_eq!(left_anchor.to_point(&buffer), Point { row: 1, column: 1 });
2718 assert_eq!(right_anchor.to_point(&buffer), Point { row: 1, column: 1 });
2719
2720 buffer.edit(vec![5..5], "ghi\n", None).unwrap();
2721 assert_eq!(buffer.text(), "adf\nbghi\nc");
2722 assert_eq!(left_anchor.to_offset(&buffer), 5);
2723 assert_eq!(right_anchor.to_offset(&buffer), 9);
2724 assert_eq!(left_anchor.to_point(&buffer), Point { row: 1, column: 1 });
2725 assert_eq!(right_anchor.to_point(&buffer), Point { row: 2, column: 0 });
2726
2727 buffer.edit(vec![7..9], "", None).unwrap();
2728 assert_eq!(buffer.text(), "adf\nbghc");
2729 assert_eq!(left_anchor.to_offset(&buffer), 5);
2730 assert_eq!(right_anchor.to_offset(&buffer), 7);
2731 assert_eq!(left_anchor.to_point(&buffer), Point { row: 1, column: 1 },);
2732 assert_eq!(right_anchor.to_point(&buffer), Point { row: 1, column: 3 });
2733
2734 // Ensure anchoring to a point is equivalent to anchoring to an offset.
2735 assert_eq!(
2736 buffer.anchor_before(Point { row: 0, column: 0 }),
2737 buffer.anchor_before(0)
2738 );
2739 assert_eq!(
2740 buffer.anchor_before(Point { row: 0, column: 1 }),
2741 buffer.anchor_before(1)
2742 );
2743 assert_eq!(
2744 buffer.anchor_before(Point { row: 0, column: 2 }),
2745 buffer.anchor_before(2)
2746 );
2747 assert_eq!(
2748 buffer.anchor_before(Point { row: 0, column: 3 }),
2749 buffer.anchor_before(3)
2750 );
2751 assert_eq!(
2752 buffer.anchor_before(Point { row: 1, column: 0 }),
2753 buffer.anchor_before(4)
2754 );
2755 assert_eq!(
2756 buffer.anchor_before(Point { row: 1, column: 1 }),
2757 buffer.anchor_before(5)
2758 );
2759 assert_eq!(
2760 buffer.anchor_before(Point { row: 1, column: 2 }),
2761 buffer.anchor_before(6)
2762 );
2763 assert_eq!(
2764 buffer.anchor_before(Point { row: 1, column: 3 }),
2765 buffer.anchor_before(7)
2766 );
2767 assert_eq!(
2768 buffer.anchor_before(Point { row: 1, column: 4 }),
2769 buffer.anchor_before(8)
2770 );
2771
2772 // Comparison between anchors.
2773 let anchor_at_offset_0 = buffer.anchor_before(0);
2774 let anchor_at_offset_1 = buffer.anchor_before(1);
2775 let anchor_at_offset_2 = buffer.anchor_before(2);
2776
2777 assert_eq!(
2778 anchor_at_offset_0
2779 .cmp(&anchor_at_offset_0, &buffer)
2780 .unwrap(),
2781 Ordering::Equal
2782 );
2783 assert_eq!(
2784 anchor_at_offset_1
2785 .cmp(&anchor_at_offset_1, &buffer)
2786 .unwrap(),
2787 Ordering::Equal
2788 );
2789 assert_eq!(
2790 anchor_at_offset_2
2791 .cmp(&anchor_at_offset_2, &buffer)
2792 .unwrap(),
2793 Ordering::Equal
2794 );
2795
2796 assert_eq!(
2797 anchor_at_offset_0
2798 .cmp(&anchor_at_offset_1, &buffer)
2799 .unwrap(),
2800 Ordering::Less
2801 );
2802 assert_eq!(
2803 anchor_at_offset_1
2804 .cmp(&anchor_at_offset_2, &buffer)
2805 .unwrap(),
2806 Ordering::Less
2807 );
2808 assert_eq!(
2809 anchor_at_offset_0
2810 .cmp(&anchor_at_offset_2, &buffer)
2811 .unwrap(),
2812 Ordering::Less
2813 );
2814
2815 assert_eq!(
2816 anchor_at_offset_1
2817 .cmp(&anchor_at_offset_0, &buffer)
2818 .unwrap(),
2819 Ordering::Greater
2820 );
2821 assert_eq!(
2822 anchor_at_offset_2
2823 .cmp(&anchor_at_offset_1, &buffer)
2824 .unwrap(),
2825 Ordering::Greater
2826 );
2827 assert_eq!(
2828 anchor_at_offset_2
2829 .cmp(&anchor_at_offset_0, &buffer)
2830 .unwrap(),
2831 Ordering::Greater
2832 );
2833 buffer
2834 });
2835 }
2836
2837 #[gpui::test]
2838 fn test_anchors_at_start_and_end(ctx: &mut gpui::MutableAppContext) {
2839 ctx.add_model(|ctx| {
2840 let mut buffer = Buffer::new(0, "", ctx);
2841 let before_start_anchor = buffer.anchor_before(0);
2842 let after_end_anchor = buffer.anchor_after(0);
2843
2844 buffer.edit(vec![0..0], "abc", None).unwrap();
2845 assert_eq!(buffer.text(), "abc");
2846 assert_eq!(before_start_anchor.to_offset(&buffer), 0);
2847 assert_eq!(after_end_anchor.to_offset(&buffer), 3);
2848
2849 let after_start_anchor = buffer.anchor_after(0);
2850 let before_end_anchor = buffer.anchor_before(3);
2851
2852 buffer.edit(vec![3..3], "def", None).unwrap();
2853 buffer.edit(vec![0..0], "ghi", None).unwrap();
2854 assert_eq!(buffer.text(), "ghiabcdef");
2855 assert_eq!(before_start_anchor.to_offset(&buffer), 0);
2856 assert_eq!(after_start_anchor.to_offset(&buffer), 3);
2857 assert_eq!(before_end_anchor.to_offset(&buffer), 6);
2858 assert_eq!(after_end_anchor.to_offset(&buffer), 9);
2859 buffer
2860 });
2861 }
2862
2863 #[test]
2864 fn test_is_dirty() {
2865 App::test_async((), |mut app| async move {
2866 let dir = temp_tree(json!({
2867 "file1": "",
2868 "file2": "",
2869 "file3": "",
2870 }));
2871 let tree = app.add_model(|ctx| Worktree::new(dir.path(), ctx));
2872 tree.flush_fs_events(&app).await;
2873 app.read(|ctx| tree.read(ctx).scan_complete()).await;
2874
2875 let file1 = app.update(|ctx| tree.file("file1", ctx)).await;
2876 let buffer1 = app.add_model(|ctx| {
2877 Buffer::from_history(0, History::new("abc".into()), Some(file1), None, ctx)
2878 });
2879 let events = Rc::new(RefCell::new(Vec::new()));
2880
2881 // initially, the buffer isn't dirty.
2882 buffer1.update(&mut app, |buffer, ctx| {
2883 ctx.subscribe(&buffer1, {
2884 let events = events.clone();
2885 move |_, event, _| events.borrow_mut().push(event.clone())
2886 });
2887
2888 assert!(!buffer.is_dirty());
2889 assert!(events.borrow().is_empty());
2890
2891 buffer.edit(vec![1..2], "", Some(ctx)).unwrap();
2892 });
2893
2894 // after the first edit, the buffer is dirty, and emits a dirtied event.
2895 buffer1.update(&mut app, |buffer, ctx| {
2896 assert!(buffer.text() == "ac");
2897 assert!(buffer.is_dirty());
2898 assert_eq!(*events.borrow(), &[Event::Edited, Event::Dirtied]);
2899 events.borrow_mut().clear();
2900
2901 buffer.did_save(buffer.version(), None, ctx);
2902 });
2903
2904 // after saving, the buffer is not dirty, and emits a saved event.
2905 buffer1.update(&mut app, |buffer, ctx| {
2906 assert!(!buffer.is_dirty());
2907 assert_eq!(*events.borrow(), &[Event::Saved]);
2908 events.borrow_mut().clear();
2909
2910 buffer.edit(vec![1..1], "B", Some(ctx)).unwrap();
2911 buffer.edit(vec![2..2], "D", Some(ctx)).unwrap();
2912 });
2913
2914 // after editing again, the buffer is dirty, and emits another dirty event.
2915 buffer1.update(&mut app, |buffer, ctx| {
2916 assert!(buffer.text() == "aBDc");
2917 assert!(buffer.is_dirty());
2918 assert_eq!(
2919 *events.borrow(),
2920 &[Event::Edited, Event::Dirtied, Event::Edited],
2921 );
2922 events.borrow_mut().clear();
2923
2924 // TODO - currently, after restoring the buffer to its
2925 // previously-saved state, the is still considered dirty.
2926 buffer.edit(vec![1..3], "", Some(ctx)).unwrap();
2927 assert!(buffer.text() == "ac");
2928 assert!(buffer.is_dirty());
2929 });
2930
2931 assert_eq!(*events.borrow(), &[Event::Edited]);
2932
2933 // When a file is deleted, the buffer is considered dirty.
2934 let events = Rc::new(RefCell::new(Vec::new()));
2935 let file2 = app.update(|ctx| tree.file("file2", ctx)).await;
2936 let buffer2 = app.add_model(|ctx: &mut ModelContext<Buffer>| {
2937 ctx.subscribe(&ctx.handle(), {
2938 let events = events.clone();
2939 move |_, event, _| events.borrow_mut().push(event.clone())
2940 });
2941
2942 Buffer::from_history(0, History::new("abc".into()), Some(file2), None, ctx)
2943 });
2944
2945 fs::remove_file(dir.path().join("file2")).unwrap();
2946 buffer2.condition(&app, |b, _| b.is_dirty()).await;
2947 assert_eq!(
2948 *events.borrow(),
2949 &[Event::Dirtied, Event::FileHandleChanged]
2950 );
2951
2952 // When a file is already dirty when deleted, we don't emit a Dirtied event.
2953 let events = Rc::new(RefCell::new(Vec::new()));
2954 let file3 = app.update(|ctx| tree.file("file3", ctx)).await;
2955 let buffer3 = app.add_model(|ctx: &mut ModelContext<Buffer>| {
2956 ctx.subscribe(&ctx.handle(), {
2957 let events = events.clone();
2958 move |_, event, _| events.borrow_mut().push(event.clone())
2959 });
2960
2961 Buffer::from_history(0, History::new("abc".into()), Some(file3), None, ctx)
2962 });
2963
2964 tree.flush_fs_events(&app).await;
2965 buffer3.update(&mut app, |buffer, ctx| {
2966 buffer.edit(Some(0..0), "x", Some(ctx)).unwrap();
2967 });
2968 events.borrow_mut().clear();
2969 fs::remove_file(dir.path().join("file3")).unwrap();
2970 buffer3
2971 .condition(&app, |_, _| !events.borrow().is_empty())
2972 .await;
2973 assert_eq!(*events.borrow(), &[Event::FileHandleChanged]);
2974 app.read(|ctx| assert!(buffer3.read(ctx).is_dirty()));
2975 });
2976 }
2977
2978 #[gpui::test]
2979 async fn test_file_changes_on_disk(mut app: gpui::TestAppContext) {
2980 let initial_contents = "aaa\nbbbbb\nc\n";
2981 let dir = temp_tree(json!({ "the-file": initial_contents }));
2982 let tree = app.add_model(|ctx| Worktree::new(dir.path(), ctx));
2983 app.read(|ctx| tree.read(ctx).scan_complete()).await;
2984
2985 let abs_path = dir.path().join("the-file");
2986 let file = app.update(|ctx| tree.file("the-file", ctx)).await;
2987 let buffer = app.add_model(|ctx| {
2988 Buffer::from_history(
2989 0,
2990 History::new(initial_contents.into()),
2991 Some(file),
2992 None,
2993 ctx,
2994 )
2995 });
2996
2997 // Add a cursor at the start of each row.
2998 let (selection_set_id, _) = buffer.update(&mut app, |buffer, ctx| {
2999 assert!(!buffer.is_dirty());
3000 buffer.add_selection_set(
3001 (0..3)
3002 .map(|row| {
3003 let anchor = buffer.anchor_at(Point::new(row, 0), AnchorBias::Right);
3004 Selection {
3005 id: row as usize,
3006 start: anchor.clone(),
3007 end: anchor,
3008 reversed: false,
3009 goal: SelectionGoal::None,
3010 }
3011 })
3012 .collect::<Vec<_>>(),
3013 Some(ctx),
3014 )
3015 });
3016
3017 // Change the file on disk, adding two new lines of text, and removing
3018 // one line.
3019 buffer.read_with(&app, |buffer, _| {
3020 assert!(!buffer.is_dirty());
3021 assert!(!buffer.has_conflict());
3022 });
3023 let new_contents = "AAAA\naaa\nBB\nbbbbb\n";
3024 fs::write(&abs_path, new_contents).unwrap();
3025
3026 // Because the buffer was not modified, it is reloaded from disk. Its
3027 // contents are edited according to the diff between the old and new
3028 // file contents.
3029 buffer
3030 .condition(&app, |buffer, _| buffer.text() != initial_contents)
3031 .await;
3032
3033 buffer.update(&mut app, |buffer, _| {
3034 assert_eq!(buffer.text(), new_contents);
3035 assert!(!buffer.is_dirty());
3036 assert!(!buffer.has_conflict());
3037
3038 let selections = buffer.selections(selection_set_id).unwrap();
3039 let cursor_positions = selections
3040 .iter()
3041 .map(|selection| {
3042 assert_eq!(selection.start, selection.end);
3043 selection.start.to_point(&buffer)
3044 })
3045 .collect::<Vec<_>>();
3046 assert_eq!(
3047 cursor_positions,
3048 &[Point::new(1, 0), Point::new(3, 0), Point::new(4, 0),]
3049 );
3050 });
3051
3052 // Modify the buffer
3053 buffer.update(&mut app, |buffer, ctx| {
3054 buffer.edit(vec![0..0], " ", Some(ctx)).unwrap();
3055 assert!(buffer.is_dirty());
3056 });
3057
3058 // Change the file on disk again, adding blank lines to the beginning.
3059 fs::write(&abs_path, "\n\n\nAAAA\naaa\nBB\nbbbbb\n").unwrap();
3060
3061 // Becaues the buffer is modified, it doesn't reload from disk, but is
3062 // marked as having a conflict.
3063 buffer
3064 .condition(&app, |buffer, _| buffer.has_conflict())
3065 .await;
3066 }
3067
3068 #[gpui::test]
3069 async fn test_set_text_via_diff(mut app: gpui::TestAppContext) {
3070 let text = "a\nbb\nccc\ndddd\neeeee\nffffff\n";
3071 let buffer = app.add_model(|ctx| Buffer::new(0, text, ctx));
3072
3073 let text = "a\nccc\ndddd\nffffff\n";
3074 let diff = buffer
3075 .read_with(&app, |b, ctx| b.diff(text.into(), ctx))
3076 .await;
3077 buffer.update(&mut app, |b, ctx| b.set_text_via_diff(diff, ctx));
3078 app.read(|ctx| assert_eq!(buffer.read(ctx).text(), text));
3079
3080 let text = "a\n1\n\nccc\ndd2dd\nffffff\n";
3081 let diff = buffer
3082 .read_with(&app, |b, ctx| b.diff(text.into(), ctx))
3083 .await;
3084 buffer.update(&mut app, |b, ctx| b.set_text_via_diff(diff, ctx));
3085 app.read(|ctx| assert_eq!(buffer.read(ctx).text(), text));
3086 }
3087
3088 #[gpui::test]
3089 fn test_undo_redo(app: &mut gpui::MutableAppContext) {
3090 app.add_model(|ctx| {
3091 let mut buffer = Buffer::new(0, "1234", ctx);
3092
3093 let edit1 = buffer.edit(vec![1..1], "abx", None).unwrap();
3094 let edit2 = buffer.edit(vec![3..4], "yzef", None).unwrap();
3095 let edit3 = buffer.edit(vec![3..5], "cd", None).unwrap();
3096 assert_eq!(buffer.text(), "1abcdef234");
3097
3098 buffer.undo_or_redo(edit1[0].edit_id().unwrap()).unwrap();
3099 assert_eq!(buffer.text(), "1cdef234");
3100 buffer.undo_or_redo(edit1[0].edit_id().unwrap()).unwrap();
3101 assert_eq!(buffer.text(), "1abcdef234");
3102
3103 buffer.undo_or_redo(edit2[0].edit_id().unwrap()).unwrap();
3104 assert_eq!(buffer.text(), "1abcdx234");
3105 buffer.undo_or_redo(edit3[0].edit_id().unwrap()).unwrap();
3106 assert_eq!(buffer.text(), "1abx234");
3107 buffer.undo_or_redo(edit2[0].edit_id().unwrap()).unwrap();
3108 assert_eq!(buffer.text(), "1abyzef234");
3109 buffer.undo_or_redo(edit3[0].edit_id().unwrap()).unwrap();
3110 assert_eq!(buffer.text(), "1abcdef234");
3111
3112 buffer.undo_or_redo(edit3[0].edit_id().unwrap()).unwrap();
3113 assert_eq!(buffer.text(), "1abyzef234");
3114 buffer.undo_or_redo(edit1[0].edit_id().unwrap()).unwrap();
3115 assert_eq!(buffer.text(), "1yzef234");
3116 buffer.undo_or_redo(edit2[0].edit_id().unwrap()).unwrap();
3117 assert_eq!(buffer.text(), "1234");
3118
3119 buffer
3120 });
3121 }
3122
3123 #[gpui::test]
3124 fn test_history(app: &mut gpui::MutableAppContext) {
3125 app.add_model(|ctx| {
3126 let mut now = Instant::now();
3127 let mut buffer = Buffer::new(0, "123456", ctx);
3128
3129 let (set_id, _) =
3130 buffer.add_selection_set(buffer.selections_from_ranges(vec![4..4]).unwrap(), None);
3131 buffer.start_transaction_at(Some(set_id), now).unwrap();
3132 buffer.edit(vec![2..4], "cd", None).unwrap();
3133 buffer.end_transaction_at(Some(set_id), now, None).unwrap();
3134 assert_eq!(buffer.text(), "12cd56");
3135 assert_eq!(buffer.selection_ranges(set_id).unwrap(), vec![4..4]);
3136
3137 buffer.start_transaction_at(Some(set_id), now).unwrap();
3138 buffer
3139 .update_selection_set(
3140 set_id,
3141 buffer.selections_from_ranges(vec![1..3]).unwrap(),
3142 None,
3143 )
3144 .unwrap();
3145 buffer.edit(vec![4..5], "e", None).unwrap();
3146 buffer.end_transaction_at(Some(set_id), now, None).unwrap();
3147 assert_eq!(buffer.text(), "12cde6");
3148 assert_eq!(buffer.selection_ranges(set_id).unwrap(), vec![1..3]);
3149
3150 now += UNDO_GROUP_INTERVAL + Duration::from_millis(1);
3151 buffer.start_transaction_at(Some(set_id), now).unwrap();
3152 buffer
3153 .update_selection_set(
3154 set_id,
3155 buffer.selections_from_ranges(vec![2..2]).unwrap(),
3156 None,
3157 )
3158 .unwrap();
3159 buffer.edit(vec![0..1], "a", None).unwrap();
3160 buffer.edit(vec![1..1], "b", None).unwrap();
3161 buffer.end_transaction_at(Some(set_id), now, None).unwrap();
3162 assert_eq!(buffer.text(), "ab2cde6");
3163 assert_eq!(buffer.selection_ranges(set_id).unwrap(), vec![3..3]);
3164
3165 // Last transaction happened past the group interval, undo it on its
3166 // own.
3167 buffer.undo(None);
3168 assert_eq!(buffer.text(), "12cde6");
3169 assert_eq!(buffer.selection_ranges(set_id).unwrap(), vec![1..3]);
3170
3171 // First two transactions happened within the group interval, undo them
3172 // together.
3173 buffer.undo(None);
3174 assert_eq!(buffer.text(), "123456");
3175 assert_eq!(buffer.selection_ranges(set_id).unwrap(), vec![4..4]);
3176
3177 // Redo the first two transactions together.
3178 buffer.redo(None);
3179 assert_eq!(buffer.text(), "12cde6");
3180 assert_eq!(buffer.selection_ranges(set_id).unwrap(), vec![1..3]);
3181
3182 // Redo the last transaction on its own.
3183 buffer.redo(None);
3184 assert_eq!(buffer.text(), "ab2cde6");
3185 assert_eq!(buffer.selection_ranges(set_id).unwrap(), vec![3..3]);
3186
3187 buffer
3188 });
3189 }
3190
3191 #[gpui::test]
3192 fn test_random_concurrent_edits(ctx: &mut gpui::MutableAppContext) {
3193 use crate::test::Network;
3194
3195 const PEERS: usize = 5;
3196
3197 for seed in 0..100 {
3198 println!("{:?}", seed);
3199 let mut rng = &mut StdRng::seed_from_u64(seed);
3200
3201 let base_text_len = rng.gen_range(0..10);
3202 let base_text = RandomCharIter::new(&mut rng)
3203 .take(base_text_len)
3204 .collect::<String>();
3205 let mut replica_ids = Vec::new();
3206 let mut buffers = Vec::new();
3207 let mut network = Network::new();
3208 for i in 0..PEERS {
3209 let buffer =
3210 ctx.add_model(|ctx| Buffer::new(i as ReplicaId, base_text.as_str(), ctx));
3211 buffers.push(buffer);
3212 replica_ids.push(i as u16);
3213 network.add_peer(i as u16);
3214 }
3215
3216 let mut mutation_count = 10;
3217 loop {
3218 let replica_index = rng.gen_range(0..PEERS);
3219 let replica_id = replica_ids[replica_index];
3220 buffers[replica_index].update(ctx, |buffer, _| match rng.gen_range(0..=100) {
3221 0..=50 if mutation_count != 0 => {
3222 let (_, _, ops) = buffer.randomly_mutate(&mut rng, None);
3223 network.broadcast(replica_id, ops, &mut rng);
3224 mutation_count -= 1;
3225 }
3226 51..=70 if mutation_count != 0 => {
3227 let ops = buffer.randomly_undo_redo(&mut rng);
3228 network.broadcast(replica_id, ops, &mut rng);
3229 mutation_count -= 1;
3230 }
3231 71..=100 if network.has_unreceived(replica_id) => {
3232 buffer
3233 .apply_ops(network.receive(replica_id, &mut rng), None)
3234 .unwrap();
3235 }
3236 _ => {}
3237 });
3238
3239 if mutation_count == 0 && network.is_idle() {
3240 break;
3241 }
3242 }
3243
3244 let first_buffer = buffers[0].read(ctx);
3245 for buffer in &buffers[1..] {
3246 let buffer = buffer.read(ctx);
3247 assert_eq!(buffer.text(), first_buffer.text());
3248 assert_eq!(
3249 buffer.all_selections().collect::<HashMap<_, _>>(),
3250 first_buffer.all_selections().collect::<HashMap<_, _>>()
3251 );
3252 assert_eq!(
3253 buffer.all_selection_ranges().collect::<HashMap<_, _>>(),
3254 first_buffer
3255 .all_selection_ranges()
3256 .collect::<HashMap<_, _>>()
3257 );
3258 }
3259 }
3260 }
3261
3262 #[gpui::test]
3263 async fn test_reparse(mut ctx: gpui::TestAppContext) {
3264 let app_state = ctx.read(build_app_state);
3265 let rust_lang = app_state
3266 .language_registry
3267 .select_language("test.rs")
3268 .cloned();
3269 assert!(rust_lang.is_some());
3270
3271 let buffer = ctx.add_model(|ctx| {
3272 let text = "fn a() {}";
3273
3274 let buffer = Buffer::from_history(0, History::new(text.into()), None, rust_lang, ctx);
3275 assert!(buffer.is_parsing);
3276 assert!(buffer.tree.is_none());
3277 buffer
3278 });
3279
3280 // Wait for the initial text to parse
3281 buffer.condition(&ctx, |buffer, _| !buffer.is_parsing).await;
3282 assert_eq!(
3283 get_tree_sexp(&buffer, &ctx),
3284 concat!(
3285 "(source_file (function_item name: (identifier) ",
3286 "parameters: (parameters) ",
3287 "body: (block)))"
3288 )
3289 );
3290
3291 // Perform some edits (add parameter and variable reference)
3292 // Parsing doesn't begin until the transaction is complete
3293 buffer.update(&mut ctx, |buf, ctx| {
3294 buf.start_transaction(None).unwrap();
3295
3296 let offset = buf.text().find(")").unwrap();
3297 buf.edit(vec![offset..offset], "b: C", Some(ctx)).unwrap();
3298 assert!(!buf.is_parsing);
3299
3300 let offset = buf.text().find("}").unwrap();
3301 buf.edit(vec![offset..offset], " d; ", Some(ctx)).unwrap();
3302 assert!(!buf.is_parsing);
3303
3304 buf.end_transaction(None, Some(ctx)).unwrap();
3305 assert_eq!(buf.text(), "fn a(b: C) { d; }");
3306 assert!(buf.is_parsing);
3307 });
3308 buffer.condition(&ctx, |buffer, _| !buffer.is_parsing).await;
3309 assert_eq!(
3310 get_tree_sexp(&buffer, &ctx),
3311 concat!(
3312 "(source_file (function_item name: (identifier) ",
3313 "parameters: (parameters (parameter pattern: (identifier) type: (type_identifier))) ",
3314 "body: (block (identifier))))"
3315 )
3316 );
3317
3318 // Perform a series of edits without waiting for the current parse to complete:
3319 // * turn identifier into a field expression
3320 // * turn field expression into a method call
3321 // * add a turbofish to the method call
3322 buffer.update(&mut ctx, |buf, ctx| {
3323 let offset = buf.text().find(";").unwrap();
3324 buf.edit(vec![offset..offset], ".e", Some(ctx)).unwrap();
3325 assert_eq!(buf.text(), "fn a(b: C) { d.e; }");
3326 assert!(buf.is_parsing);
3327 });
3328 buffer.update(&mut ctx, |buf, ctx| {
3329 let offset = buf.text().find(";").unwrap();
3330 buf.edit(vec![offset..offset], "(f)", Some(ctx)).unwrap();
3331 assert_eq!(buf.text(), "fn a(b: C) { d.e(f); }");
3332 assert!(buf.is_parsing);
3333 });
3334 buffer.update(&mut ctx, |buf, ctx| {
3335 let offset = buf.text().find("(f)").unwrap();
3336 buf.edit(vec![offset..offset], "::<G>", Some(ctx)).unwrap();
3337 assert_eq!(buf.text(), "fn a(b: C) { d.e::<G>(f); }");
3338 assert!(buf.is_parsing);
3339 });
3340 buffer.condition(&ctx, |buffer, _| !buffer.is_parsing).await;
3341 assert_eq!(
3342 get_tree_sexp(&buffer, &ctx),
3343 concat!(
3344 "(source_file (function_item name: (identifier) ",
3345 "parameters: (parameters (parameter pattern: (identifier) type: (type_identifier))) ",
3346 "body: (block (call_expression ",
3347 "function: (generic_function ",
3348 "function: (field_expression value: (identifier) field: (field_identifier)) ",
3349 "type_arguments: (type_arguments (type_identifier))) ",
3350 "arguments: (arguments (identifier))))))",
3351 )
3352 );
3353
3354 buffer.update(&mut ctx, |buf, ctx| {
3355 buf.undo(Some(ctx));
3356 assert_eq!(buf.text(), "fn a() {}");
3357 assert!(buf.is_parsing);
3358 });
3359 buffer.condition(&ctx, |buffer, _| !buffer.is_parsing).await;
3360 assert_eq!(
3361 get_tree_sexp(&buffer, &ctx),
3362 concat!(
3363 "(source_file (function_item name: (identifier) ",
3364 "parameters: (parameters) ",
3365 "body: (block)))"
3366 )
3367 );
3368
3369 buffer.update(&mut ctx, |buf, ctx| {
3370 buf.redo(Some(ctx));
3371 assert_eq!(buf.text(), "fn a(b: C) { d.e::<G>(f); }");
3372 assert!(buf.is_parsing);
3373 });
3374 buffer.condition(&ctx, |buffer, _| !buffer.is_parsing).await;
3375 assert_eq!(
3376 get_tree_sexp(&buffer, &ctx),
3377 concat!(
3378 "(source_file (function_item name: (identifier) ",
3379 "parameters: (parameters (parameter pattern: (identifier) type: (type_identifier))) ",
3380 "body: (block (call_expression ",
3381 "function: (generic_function ",
3382 "function: (field_expression value: (identifier) field: (field_identifier)) ",
3383 "type_arguments: (type_arguments (type_identifier))) ",
3384 "arguments: (arguments (identifier))))))",
3385 )
3386 );
3387
3388 fn get_tree_sexp(buffer: &ModelHandle<Buffer>, ctx: &gpui::TestAppContext) -> String {
3389 buffer.read_with(ctx, |buffer, _| {
3390 buffer.tree.as_ref().unwrap().0.root_node().to_sexp()
3391 })
3392 }
3393 }
3394
3395 impl Buffer {
3396 fn random_byte_range(&mut self, start_offset: usize, rng: &mut impl Rng) -> Range<usize> {
3397 let end = self.clip_offset(rng.gen_range(start_offset..=self.len()), Bias::Right);
3398 let start = self.clip_offset(rng.gen_range(start_offset..=end), Bias::Left);
3399 start..end
3400 }
3401
3402 pub fn randomly_edit<T>(
3403 &mut self,
3404 rng: &mut T,
3405 old_range_count: usize,
3406 ctx: Option<&mut ModelContext<Self>>,
3407 ) -> (Vec<Range<usize>>, String, Vec<Operation>)
3408 where
3409 T: Rng,
3410 {
3411 let mut old_ranges: Vec<Range<usize>> = Vec::new();
3412 for _ in 0..old_range_count {
3413 let last_end = old_ranges.last().map_or(0, |last_range| last_range.end + 1);
3414 if last_end > self.len() {
3415 break;
3416 }
3417 old_ranges.push(self.random_byte_range(last_end, rng));
3418 }
3419 let new_text_len = rng.gen_range(0..10);
3420 let new_text: String = RandomCharIter::new(&mut *rng).take(new_text_len).collect();
3421
3422 let operations = self
3423 .edit(old_ranges.iter().cloned(), new_text.as_str(), ctx)
3424 .unwrap();
3425
3426 (old_ranges, new_text, operations)
3427 }
3428
3429 pub fn randomly_mutate<T>(
3430 &mut self,
3431 rng: &mut T,
3432 mut ctx: Option<&mut ModelContext<Self>>,
3433 ) -> (Vec<Range<usize>>, String, Vec<Operation>)
3434 where
3435 T: Rng,
3436 {
3437 // Randomly edit
3438 let (old_ranges, new_text, mut operations) =
3439 self.randomly_edit(rng, 5, ctx.as_deref_mut());
3440
3441 // Randomly add, remove or mutate selection sets.
3442 let replica_selection_sets = &self
3443 .all_selections()
3444 .map(|(set_id, _)| *set_id)
3445 .filter(|set_id| self.replica_id == set_id.replica_id)
3446 .collect::<Vec<_>>();
3447 let set_id = replica_selection_sets.choose(rng);
3448 if set_id.is_some() && rng.gen_bool(1.0 / 6.0) {
3449 let op = self.remove_selection_set(*set_id.unwrap(), None).unwrap();
3450 operations.push(op);
3451 } else {
3452 let mut ranges = Vec::new();
3453 for _ in 0..5 {
3454 ranges.push(self.random_byte_range(0, rng));
3455 }
3456 let new_selections = self.selections_from_ranges(ranges).unwrap();
3457
3458 let op = if set_id.is_none() || rng.gen_bool(1.0 / 5.0) {
3459 self.add_selection_set(new_selections, None).1
3460 } else {
3461 self.update_selection_set(*set_id.unwrap(), new_selections, None)
3462 .unwrap()
3463 };
3464 operations.push(op);
3465 }
3466
3467 (old_ranges, new_text, operations)
3468 }
3469
3470 pub fn randomly_undo_redo(&mut self, rng: &mut impl Rng) -> Vec<Operation> {
3471 let mut ops = Vec::new();
3472 for _ in 0..rng.gen_range(1..5) {
3473 if let Some(edit_id) = self.history.ops.keys().choose(rng).copied() {
3474 ops.push(self.undo_or_redo(edit_id).unwrap());
3475 }
3476 }
3477 ops
3478 }
3479
3480 fn selections_from_ranges<I>(&self, ranges: I) -> Result<Vec<Selection>>
3481 where
3482 I: IntoIterator<Item = Range<usize>>,
3483 {
3484 static NEXT_SELECTION_ID: AtomicUsize = AtomicUsize::new(0);
3485
3486 let mut ranges = ranges.into_iter().collect::<Vec<_>>();
3487 ranges.sort_unstable_by_key(|range| range.start);
3488
3489 let mut selections = Vec::with_capacity(ranges.len());
3490 for range in ranges {
3491 if range.start > range.end {
3492 selections.push(Selection {
3493 id: NEXT_SELECTION_ID.fetch_add(1, atomic::Ordering::SeqCst),
3494 start: self.anchor_before(range.end),
3495 end: self.anchor_before(range.start),
3496 reversed: true,
3497 goal: SelectionGoal::None,
3498 });
3499 } else {
3500 selections.push(Selection {
3501 id: NEXT_SELECTION_ID.fetch_add(1, atomic::Ordering::SeqCst),
3502 start: self.anchor_after(range.start),
3503 end: self.anchor_before(range.end),
3504 reversed: false,
3505 goal: SelectionGoal::None,
3506 });
3507 }
3508 }
3509 Ok(selections)
3510 }
3511
3512 pub fn selection_ranges<'a>(&'a self, set_id: SelectionSetId) -> Result<Vec<Range<usize>>> {
3513 Ok(self
3514 .selections(set_id)?
3515 .iter()
3516 .map(move |selection| {
3517 let start = selection.start.to_offset(self);
3518 let end = selection.end.to_offset(self);
3519 if selection.reversed {
3520 end..start
3521 } else {
3522 start..end
3523 }
3524 })
3525 .collect())
3526 }
3527
3528 pub fn all_selections(&self) -> impl Iterator<Item = (&SelectionSetId, &[Selection])> {
3529 self.selections
3530 .iter()
3531 .map(|(set_id, selections)| (set_id, selections.as_ref()))
3532 }
3533
3534 pub fn all_selection_ranges<'a>(
3535 &'a self,
3536 ) -> impl 'a + Iterator<Item = (SelectionSetId, Vec<Range<usize>>)> {
3537 self.selections
3538 .keys()
3539 .map(move |set_id| (*set_id, self.selection_ranges(*set_id).unwrap()))
3540 }
3541 }
3542
3543 impl Operation {
3544 fn edit_id(&self) -> Option<time::Local> {
3545 match self {
3546 Operation::Edit { edit, .. } => Some(edit.id),
3547 Operation::Undo { undo, .. } => Some(undo.edit_id),
3548 Operation::UpdateSelections { .. } => None,
3549 }
3550 }
3551 }
3552}