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